git checkout 对工作目录的影响

问题的提出

本文要讨论的是:当我们用git checkout <branch_name>命令切换分支时,如果有未提交的修改,会发生什么?

如果当前工作区的状态是“clean”,那么切换到其他分支是很容易的。但是,如果有未提交的修改,也许就不能顺利地切换过去,Git 会给出错误信息。例如:

 $ git branch
      bug/pr-1
      bug/pr-2
      dev
    * master
    
$ git checkout dev
    error: Your local changes to the following files would be overwritten by checkout:
        NewStuff
    Please, commit your changes or stash them before you can switch branches.
    Aborting

Git 提示我们:要么提交所有的修改,要么用 stash 命名把这些修改储藏起来。

让人费解的是,Git 也不是每一次都这样阻止我们切换分支。比如当我们基于活跃分支的最近一次提交创建一个新分支的时候,不管本地有没有未提交的修改,我们都可以切换到新分支,这又是为何呢?

原理初探

假设你当前在分支 branch1, 你想切换到分支 branch2,于是你输入命令

git checkout branch2

对于你的工作区来说,这条命令意味着什么呢?

  1. 对于每一个在分支1但是不在分支2的文件,Git 会删除它们;
  2. 对于每一个在分支2但是不在分支1中的文件,Git 会创建它们(用合适的内容);
  3. 对于每一个既在分支1又在分支2的文件,如果版本不同,那么 Git 会更新工作区的文件,使之和分支2的版本匹配。

上面的每一步都有可能破坏你当前的工作区(工作区和暂存区对于每个分支是共用的)。

对于1,删除一个文件,如果这个文件在工作区的版本和它在分支1的版本是一致的,那么删除它就是安全的;如果你修改了它,还没有提交,那么删除就是不安全的;

对于2,创建一个文件,如果工作区还不存在这个文件,那就是安全的;如果工作区已经有这个文件,但是内容是“错”的,那么就不安全;

对于3,如果这个文件已经提交,那么就是安全的;如果被修改了,且没有提交,那么就不安全;

注意:用命令git checkout -b <newbranch>创建并切换到一个新分支总是“安全”的:没有文件被创建,也没有文件被删除,也没有文件被更新,索引也没有任何改变。

但是用git checkout -b <newbranch> <start_point>就不一样了。Git 会应用上述的安全检查规则。





参考资料

https://stackoverflow.com/questions/22053757/checkout-another-branch-when-there-are-uncommitted-changes-on-the-current-branch

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐