我在 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 check out 文件”
现在假设我有一个 repo 和一个文件 test.txt
在里面
起初工作目录是干净的:
On branch master
nothing to commit, working tree clean
现在我修改 test.txt
, 运行 git add
和 git 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
的版本在 index 中应该保持不变 并且它在工作目录中的版本应该已经改回它在 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 的内容:
Overwrite the contents of the files that match the pathspec. When the
<tree-ish>
(most often a commit) is not given, overwrite working tree with the contents in the index. When the<tree-ish>
is given, overwrite both the index and the working tree with the contents at the<tree-ish>
.
您处于第二种情况,<tree-ish>
给出 ( HEAD
),这是预期的行为:索引和工作目录都被旧版本的 test.txt
覆盖。 .
相反,如果您使用 git checkout test.txt
, 和 test.txt
已经上演,工作目录或索引都没有改变,因为您基本上是用索引版本替换工作目录版本,但显然是相同的。
Atlassian 文章试图表达的是:
-
git checkout <pathspec>
主要在工作目录上运行(如果提供了<tree-ish>
,也会在索引上运行) -
git reset
仅对索引进行操作。
误会的产生是因为在git reset
<tree-ish>
默认为 HEAD
.相反,git checkout
如果指定 <tree-ish>
则行为不同还是不是。
关于git - 为什么 git checkout 文件的行为类似于重置暂存文件,然后 check out 未暂存文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66483574/