英文:
Git Index has files without using `add`
问题
git
索引允许我们指定要放入新tree
对象的文件 - 这样的tree
对象是任何新创建的commit
对象将指向的。
我知道使用git add <filename>
将文件放入索引,以便生成一个tree
。
然而,索引似乎在文件添加到索引之前就存储了这些文件。运行以下命令后,即使一个"clean"目录也会显示与由HEAD
指向的提交相同的文件。
git ls-files --stage
(我认为这会显示index
中的文件,因为stage
与 index
同义)
为什么git
会在索引中存储"未添加"的文件?这些文件不是通过查看HEAD
可用吗?这似乎是多余的。
当阅读某些man
页面时,HEAD、索引和工作树之间的区别变得更加模糊。例如,这是从man git-restore
中提取的。
> 默认情况下,如果给出了--staged,内容将从HEAD恢复,否则从索引恢复
- 我认为如果编辑了
b.txt
但未将其添加到索引(即git status
显示红色字母),那么index
中的b.txt
版本与HEAD
中的版本相同。然而,git restore --staged -- b.txt
不起作用,而git restore -- b.txt
将工作树恢复到HEAD
提交中的版本。 - 如果
stage
与index
同义,那么为什么--staged
在这个man
页面中指的是HEAD
?
英文:
The git
index allows us to specify the files that go into a new tree
object - such a tree
object is what any newly created commit
object will point to.
I'm aware that using git add <filename>
puts a file into the index so that a tree can be generated.
However, the index seems to store files even before they have been added to the index. After running the following command, even a "clean" directory will display all the same files as the commit pointed to by HEAD
.
git ls-files --stage
(I assume that this displays the files in the index
because stage
is synonymous with index
)
Why would git
store "un-added" files in the index? Aren't these files available by looking at HEAD
? This seems redundant.
The distinction between HEAD, index, and working tree gets even murkier when reading certain man
pages. For example, this is from man git-restore
.
> By default, if --staged is given, the contents are restored from HEAD, otherwise from the index
- I would think that if
b.txt
is edited but not added to the index (i.e.git status
shows red letters), then the version ofb.txt
in theindex
is the same as inHEAD
. However,git restore --staged -- b.txt
does nothing whereasgit restore -- b.txt
restores the working tree to the version in theHEAD
commit. - If
stage
is synonymous withindex
then why would--staged
refer toHEAD
in thisman
page?
答案1
得分: 2
不要使用 git ls-files --stage
命令来检查你暂存的文件,使用 git status
。
当一个人和另一个人讨论关于 git 时,通常会用 "索引" 来指代你在仓库中 已经暂存的更改。
但是从 git 内部的角度来看:"索引" 其实是 当前 HEAD 提交的内容 加上你已经暂存的更改。
举个简单的例子:当你运行 git diff --cached
命令时,它比较的是 索引 和当前 HEAD 提交,那些没有被修改的文件不会被报告为从索引中 "丢失" 的。
git ls-files --stage
命令只会报告索引的内容(git 内部的索引)。在某些特定情况下,可能会有人对这些信息感兴趣,但通常用户会使用 git status
。
关于 git restore
:我认为有关 git restore
的 --staged
选项和 git diff
的 --cached
选项存在混淆。
([编辑] 我也会说,在 git 团队的部分中,将 -s
,-S
,--source
和 --staged
这些选项愉快地结合在一起,实际上相当误导人,我在搞清楚这个命令的含义之前也头疼了好几次。尽管我认为这些用例是有意义的。)
请注意,git restore
中的 --staged
选项的含义 非常不同:它指定了 你想要写入文件的位置,也就是说 "在 git 存储中,在索引中" 与 "在磁盘上,在工作树中"(我的 "与" 也是误导:实际上你可以使用 git restore -SW
来同时指定这两个选项)。
引用文档:
> -W, --worktree
> -S, --staged
>
> 指定还原的位置。如果没有指定任何选项,默认情况下会还原到工作树。指定 --staged
选项只会还原到索引。指定两者都会同时还原。
你引用的文档是关于 -s|--source
选项的:如果指定了 -S|--staged
选项,那么 --source
的默认值 就不同。
所以:如果一个文件 b.txt
没有暂存的更改,这意味着该文件在索引中的内容与 HEAD 的内容相同,正如你正确观察到的那样,git restore --staged -- b.txt
不会产生任何效果。
--staged
的用法是针对其他情况的:
- 如果文件
b.txt
有暂存的更改,那么git restore --staged -- b.txt
将会 取消已暂存的更改 git restore -s that/other/commit --staged -- b.txt
会将b.txt
的内容从that/other/commit
放入索引中,而不改变工作树- 等等 ...
英文:
Don't use git ls-files --stage
to check your staged files, use git status
.
When a human talks to another human about git, she/he generally uses "the index" to refer to the changes you have staged in your repo.
But from the point of view git internals: "the index" is actually the content of the current HEAD commit plus the changes you have staged.
To give a simple illustration: when you run git diff --cached
, which compares the index with the current HEAD commit, files that haven't been modified are not reported as "missing" from the index.
git ls-files --stage
just reports the content of the index (the git internal one). There are some specific cases when one may be interested in that information, but generally users are looking for git status
.
Regarding git restore
: I think there is a confusion between the --staged
option for git restore
and the --cached
option for git diff
.
([edit] I will also say that it is pretty misleading, on the git team part, to have a command which happily combines -s
,-S
,--source
and --staged
, and I also had a few headaches before I figured out what was what with that command. The use cases make sense though, imho.)
Note that the meaning of --staged
for git restore
is very different : it specifies where you want to write your files, as in "in git storage, in the index" versus "on disk, in the worktree" (my "versus" is also misleading: you can actually ask for both with git restore -SW
).
quoting the doc:
> -W, --worktree
> -S, --staged
>
> Specify the restore location. If neither option is specified, by default the working tree is restored. Specifying --staged will only restore the index. Specifying both restores both.
The documentation you quote is the one for -s|--source
: if -S|--staged
is specified, then the default value for --source
is not the same.
So : if a file b.txt
has no staged modifications, this means that the index content for that file is the same as HEAD's content, and, as you correctly observed, git restore --staged -- b.txt
is a no-op.
The uses of --staged
are the other cases:
git restore --staged -- b.txt
would unstage staged changes if there were anygit restore -s that/other/commit --staged -- b.txt
will put in the index the content ofb.txt
coming fromthat/other/commit
, without changing the worktree- etc ...
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论