2

我在 git 文档中遇到过这个声明:

Checking out a file is similar to using git reset with a file path, except it updates the working directory instead of the stage

链接:https ://www.atlassian.com/git/tutorials/resetting-checking-out-and-reverting

部分:“Git 签出文件”

现在假设我有一个仓库和一个test.txt文件

起初工作目录是干净的:

On branch master
nothing to commit, working tree clean

现在我修改 test.txt、运行git addgit status显示:

On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   test.txt

现在我运行git checkout HEAD test.txt并得到:

Updated 1 path from 58e7043

输出git status

On branch master
nothing to commit, working tree clean

根据文档,test.txt索引中版本应该保持不变,并且工作目录中的版本应该已经更改回 HEAD 指向的提交中的版本,从而导致工作之间的文件版本不同目录和索引——>在这种情况下不应该git status输出什么?但git status没有表明 - 为什么?

通常要从暂存文件到清理工作树,我必须先使用git reset HEAD <filename>git checkout HEAD <filename>文件,但这里似乎两者都做

我很困惑

编辑 - 有趣的是,如果在暂存文件后test.txt我运行git checkout test.txt而不是git checkout HEAD test.txt得到:

Updated 0 paths from the index

即使这两种形式应该是等价的,而前者HEAD也默认为(?)

我又糊涂了

4

1 回答 1

3

首先,这不是官方文档,在我看来,这是一个案例,Atlassian 在两个命令之间的比较上非常肤浅。有时,就像这次一样,同一个 git 命令会根据您使用的选项执行非常不同的操作。在 SO 上,您可以找到深入探讨该主题的好答案。

只是为了回答您的问题,以下是官方文档中有关git checkoutpathspec 的内容

覆盖与路径规范匹配的文件的内容。当 <tree-ish>没有给出(通常是提交)时,用索引中的内容覆盖工作树。当<tree-ish>给出 时,用 . 的内容覆盖索引和工作树 <tree-ish>

您处于第二种情况,其中<tree-ish>给出 ( HEAD),这是预期的行为:索引和工作目录都被旧版本的test.txt.

相反,如果您使用git checkout test.txt, 并且test.txt已经暂存,则工作目录或索引都不会更改,因为您基本上是用索引版本替换工作目录版本,但显然是相同的。

Atlassian 的文章想说的是:

  • git checkout <pathspec>主要在工作目录上运行(如果<tree-ish>提供了 a 也在索引上)
  • git reset仅对索引进行操作。

产生了误解,因为git reset默认<tree-ish>HEAD. 相反,git checkout如果您指定 a<tree-ish>或不指定,则行为会有所不同。

于 2021-03-04T22:45:53.237 回答