为什么 git 检出文件的行为类似于重置暂存文件,然后检出未暂存文件?
Why does git checkout file behave like reset staged file followed by checkout unstaged file?
我在 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
Link:https://www.atlassian.com/git/tutorials/resetting-checking-out-and-reverting
部分:“Git 签出文件”
现在假设我有一个 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
的版本应该保持不变及其版本在工作目录中应该在 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
),这是预期的行为:索引和工作目录都被旧版本的 [= 覆盖16=].
相反,如果您使用 git checkout test.txt
,并且 test.txt
已经上演,工作目录或索引都不会改变,因为您基本上是用索引版本替换工作目录版本,但是明明是一样的
Atlassian 文章想表达的是:
git checkout <pathspec>
主要在工作目录上运行(如果提供了 <tree-ish>
,也会在索引上运行)
git reset
仅对索引进行操作。
产生误解是因为在git reset
中<tree-ish>
默认为HEAD
。相反,如果您指定 <tree-ish>
或不指定 git checkout
,则 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
Link:https://www.atlassian.com/git/tutorials/resetting-checking-out-and-reverting
部分:“Git 签出文件”
现在假设我有一个 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
的版本应该保持不变及其版本在工作目录中应该在 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
),这是预期的行为:索引和工作目录都被旧版本的 [= 覆盖16=].
相反,如果您使用 git checkout test.txt
,并且 test.txt
已经上演,工作目录或索引都不会改变,因为您基本上是用索引版本替换工作目录版本,但是明明是一样的
Atlassian 文章想表达的是:
git checkout <pathspec>
主要在工作目录上运行(如果提供了<tree-ish>
,也会在索引上运行)git reset
仅对索引进行操作。
产生误解是因为在git reset
中<tree-ish>
默认为HEAD
。相反,如果您指定 <tree-ish>
或不指定 git checkout
,则 git checkout
的行为会有所不同。