摘要:分支切换在Git的使用中可谓是最重要的部分之一,而git checkout还经常被用于回滚当前工作目录——当然,也被用来做 分支切换。因此,这是出错率极高的命令。本文主要为你解析git checkout的两个如标题总的特殊错误,然后分析git checkout的回滚作用。
When <paths> are not given, this command switches branches byupdating the index, working tree, and HEAD to reflect the specified branch.
[huangyk@huangyk quickstart]$ git checkout testone
error: You have local changes to 'test'; cannot switch branches.
出现上述信息,原因在于你的当前目录下,有一个文件test是修改状态,但是并没有进入index,我们将它add进入index,然后看看结果:
[huangyk@huangyk quickstart]$ git add test
[huangyk@huangyk quickstart]$ git checkout testoneerror: Entry 'test' would be overwritten by merge. Cannot merge.
很显然,我们可能已经猜到,这个时候需要commit test ,然后才能进行分支转化,为什么会这样呢?
我们都知道,一个git目录,仅仅有一个当前工作目录区域和一个index区域。我们切换分支,如果Head发生了变化,意味着HEAD\index\local的内容都要发生改变,工作目录和index都是clean的,那么可以直接check out;如果local/index在分支转换前后不同,同时会产生冲突,那么就必然会报错,而不允许转换。
这样,我们已经猜到了,保持clean状态,就可以切换了。
git不支持branch 和path两个参数同时使用
好了,我们来看git checkout前后文件内容的变化:
[huangyk@huangyk quickstart]$ ls 15L.sh eth.boot eth.conf eth.nm lab.sh nat.sh netconfig.sh networkmanager.sh test [huangyk@huangyk quickstart]$ git checkout testone Switched to branch 'testone' [huangyk@huangyk quickstart]$ ls 15L.sh eth.boot eth.conf eth.nm lab.sh nat.sh netconfig.sh networkmanager.sh testone
看到了吗?从中可以看出,git checkout branch的原则是::Head/index/local都发生了改变。
现在,我们使用git branch 创建分支,然后再运行git checkout,发现这个现象:
即当前分支并不是干净的,checkout 后面的分支是干净的,也能checkout成功,可见我们使用git checkout branch的时候,本来打算用branch的文件更新working dir的文件,但是没有作出任何更改。
即使同样的分支状态:
[huangyk@huangyk quickstart]$ git status # On branch testone # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: testone # # Changed but not updated: # (use "git add <file>..." to update what will be committed) # (use "git checkout -- <file>..." to discard changes in working directory) # # modified: testone [huangyk@huangyk quickstart]$ git checkout master
error: Entry 'testone' would be overwritten by merge. Cannot merge. [huangyk@huangyk quickstart]$ git branch anothertwo [huangyk@huangyk quickstart]$ git checkout anothertwo M testone Switched to branch 'anothertwo'
看见了吗?不能checkout master,但是可以checkout anotertwo:
分析:对于checkout master,存在冲突是很好理解的。对于anothertwo,因为another two和 testone新近的提交点相同,所以效果和在一个分支内部进行checkout的效果。所以,我们猜想,checkout 会比较目标Head和当前Head:如果不同,那么执行head/index/working dir的全面覆盖(可能失败);如果Head并没有发生变化,那么先切换分支,然后对比index和working dir的变化,而且并不会改变它们。
git checkout的分支内部使用参考这里