为什么 git checkout 文件的行为类似于重置暂存文件,然后签出未暂存文件?

问题描述

我在 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 Checkout 文件

现在假设我有一个仓库和一个文件 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

根据文档,indextest.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 (?)

我又糊涂了

解决方法

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

为了回答您的问题,以下是关于 git checkout with a pathspec 的官方文档:

覆盖与路径规范匹配的文件的内容。当。。。的时候 <tree-ish>(最常见的是提交)未给出,覆盖工作树 与索引中的内容。当给出 <tree-ish> 时, 用位于的内容覆盖索引和工作树 <tree-ish>

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

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

Atlassian 文章想说的是:

  • test.txt 主要对工作目录进行操作(如果提供了 git checkout <pathspec>,也会对索引进行操作)
  • <tree-ish> 仅对索引进行操作。

产生误解是因为在 git resetgit reset 默认为 <tree-ish>。相反,如果您指定 HEADgit checkout 的行为会有所不同。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...