git checkout
是 git 众多让新手困惑的原因之一。因为它的作用依赖于上下文。
git checkout 切换分支
人们大多使用它切换本地活动分支。准确来讲,是重置 HEAD 指针到另一个分支<small>( 的末端 Commit )</small>。例如,当你在 main 分支时,你可以切换到 develop 分支。
git checkout develop
你也可以用某个 commit 来代替 HEAD 指针取代分支名<small>( 切换到所谓的 分离 HEAD 状态</small>:
git checkout 64bc64ad2a26fef56c22c194f71de41cf85b0bad
但是,如果你用文件名替换分支名或 commit 指针,事情就变的很奇怪:它会丢弃你对文件在工作区的修改,把文件还原到分支中的状态。
例如,你切换到 develop 分支,修改了 test.txt 文件,你可以将文件还原到当前分支最近一次 commit 的状态:
git checkout -- test.txt
为什么会这样
如果你第一次看到这种行为,你会认为它没法理解,为什么一个命令却有两种行为?原因比看上去微妙。如果你看 git documentation,就能看到,这还有个经常被忽略的参数:
git checkout <tree-ish> -- <pathspec>
这里的 <tree-ish>
是什么?
它可以表示很多不同的东西,但最常用的是「commit hash」或「分支名」。默认值是当前分支,但它可以是任何其它分支或 commit。 所以如果你想把当前 develop 分支中的 test.txt 文件切换成 main 分支中的版本,你可以这么干:
git checkout main -- test.txt
这个搞明白了,事情就变得好理解了。当只提供一个分支名或 commit 作为 git checkout 的参数,它会修改所有文档到相应的版本,但如果你指定了文件名,它只会修改此文件到相应的版本。
网友评论