Git的暂存区只是一个索引吗?

29
《Pro Git》这本书指出,暂存区只是一个列表或索引,它告诉我们哪些文件会在执行`git commit`命令时被提交,现在“索引”更常被称为“暂存区”。
但如果我们修改已经存在于仓库中的文件`foo.txt`,并使用`git add foo.txt`命令将其加入暂存区,然后再次修改该文件,此时该文件既处于“已暂存”又处于“已修改”的状态(可以通过`git status`命令查看),如果我们继续执行`git commit`命令,则“已暂存”的版本将被提交,而第二次修改不会被包括在内。
那么,“暂存区”如何跟踪第一次修改呢?它只是一个文件列表,怎么可能做到呢?
6个回答

26

Index是您的工作目录的视图,已准备好进行提交。它可以被看作是一个预提交状态,不仅仅是"文件列表"那么简单。当您执行git add命令时,该更改的文件将会被添加至Index中,并且只有在您添加了更新后,这些更新才能被看到。


2
这是一个相当古老的问题,但我仍然找不到关于“暂存区和索引是否相同”的答案。因为无论我去哪里查找,都显示git add实际上是将文件添加到索引中,同时git add也将文件放入暂存区(即在提交之前文件所处的区域)。所以,“索引”和“暂存区”概念是相同的吗?我认为清楚术语和这两个术语之间的差异(如果有的话)非常重要。 - undefined

5
索引就像一个已完成工作的出篮。你可以在任何时候将(部分)完成的文件添加到该出篮中,并用当前副本替换以前的副本,因此当你最终决定提交时,它将使用该出篮(当前的索引)的内容来创建提交。
此外,你之前的添加操作将在存储库中创建一个blob对象,如果需要,可以通过各种日志找到它。经过一段时间(30天+),它将被gc清除。

2
我喜欢你关于“输出篮子”的例子,但你并没有提到它与分阶段有什么关系。 - Ethan Davis
3
@EthanDavis 中的“暂存区”在很大程度上与“索引”相同,不同之处更多是从不同角度的看法。暂存区是用户的概念视图,而索引更像是 Git 开发人员的视角(他们保留了“暂存区”中的列表)。Git 有许多以开发人员为命名对象,这些对象被用户误解了;-) - Philip Oakley

4
那么,如果“暂存区”只是一个索引(即列表),它如何跟踪第一个编辑是什么呢?
索引是一组名称和指向内容的指针。在书籍中,它是页码;在Git索引中,它是存储库对象数据库中的对象ID。这就是Git索引的作用,即基于路径名的内容指针列表。
因此,对于某个路径名,执行“git add”操作本质上就是将其相应的内容指针添加到Git索引中。
sha=`git hash-object -w path/to/it`
git update-index --cacheinfo 100644,$sha,path/to/it 

除了 git add 外,还会检查可执行文件并对其使用 100755,并进行递归添加、检查您的 .gitignore 和其他看起来通常最方便的内容。它是将内容添加到对象数据库并更新索引的方便命令。

3

前三个词是正确的,后面的都是错误的。 - jthill

0

暂存区不仅仅是一个列表或索引,用于确定在git提交时哪些文件将会被提交。

如果仅仅是个简单的列表,那么 git add 就不能像广告说的那样工作。

相反, git add 必须保存给定命令时文件的内容。因此它会快照文件,然后将这些快照放入暂存区(也称为“索引”,但在我看来这是一个非常糟糕的名称)。

所以,是的,事实上,本书的陈述是误导性和令人困惑的。但这并不太奇怪。许多git文档都很混乱而且思路不清晰。

继续评价我吧。我相信我是正确的。


你对此有误。索引就是一个索引。称其为暂存区是为了向那些以前从未在版本控制系统中遇到过这种东西的人解释为什么你需要在版本控制系统中使用这样的东西。 - jthill

0
索引实际上不是我们在项目中看到的文件列表。它是一个将出现在我们即将提交的快照中的blob列表。
将blob视为包含特定文件(例如特定时刻的foo.txt)压缩内容的文件。(更多信息请参阅这里
当您使用例如git add foo.txt将文件添加到暂存区时,会生成一个新的blob,其中包含您将其添加到暂存区时文件的内容。我们可以通过使用git ls-file -s来查看。我们将看到类似于以下内容:
100644 9cdf71db89dabc03936d7e685d812272e8976274 0 foo.txt
所以,如果我们进行任何更改,我们仍然在一个“blob”中存储了先前的内容,并且“index”文件仍然引用它(即其SHA1哈希“9cdf71db89...”)。
(实际的“blob”存储在“.git/9c/df71db89...”中,要查看其内容,我们可以使用“git cat-file -p 9cdf71db89da”命令。)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接