理解git status的short标志输出

5
$ git status -s
 M README
MM Rakefile
A  lib/git.rb
M  lib/simplegit.rb
?? LICENSE.txt

输出结果有两列 - 左边的列指暂存区的状态,右边的列指工作树的状态。例如,在该输出中,README文件在工作目录中被修改但尚未暂存,而lib/simplegit.rb文件被修改并已暂存。 Rakefile被修改、暂存,然后再次修改,因此对它进行了既暂存又未暂存的更改。
以上内容摘自Scott Chacon和Ben Straub编写、Apress出版的《Pro Git》。
我对暂存区和工作树之间的区别感到困惑。我将解释我所相信的事实。
“README文件在工作目录中被修改但尚未暂存”:我们没有跟踪这个文件。但是,Git知道它已被修改,从上一个快照开始。
“lib/simplegit.rb文件被修改并已暂存”:修改后,我们已经将文件暂存。现在只需提交即可。
“Rakefile被修改、暂存,然后再次修改,因此对它进行了既暂存又未暂存的更改。”:与前一个文件一样,我们已经暂存了修改后的文件。接下来做什么?

https://www.git-scm.com/docs/git-status#_short_format - ElpieKay
问题是什么?如果您不知道“修改”和“暂存”是什么意思,我建议您在此处阅读:https://git-scm.com/book/en/v2/Getting-Started-Git-Basics - jbe
2个回答

8
“README文件在工作目录中被修改但尚未暂存”:我们没有跟踪此文件。但是,Git知道它已被修改,并从最后一个快照开始追踪。不,这是错误的:具体来说,该文件已经被暂存(并且暂存副本与HEAD副本匹配,这使得该文件被跟踪)。关于暂存区的棘手部分在于它通常几乎是看不见的。这会让人们误解它的工作原理。首先,让我们解释一些Git术语。在这个阶段,有三个感兴趣的实体:当前提交、暂存区(实际上有三个名称)和工作树。暂存区的三个名称是“索引(index)”,“暂存区(staging-area)”和“缓存(cache)”,这三个名称反映了Linus Torvald最初选择的低质量(“索引(index)”)或隐形暂存区的巨大重要性,或者两者兼而有之。(我认为两者都有。)让我们更深入地了解每一个实体。
  • 当前的提交,我们也可以通过名称 HEAD (全部大写1 )来命名,它当然是一个提交-它是在您(或其他人)运行 git commit 时在暂存区中的所有文件的快照。此快照是永久的(大多数情况下)和只读的(完全)。它的真实名称不是 HEAD -那只是我们现在可以找到它的符号名称-而是一些庞大丑陋的哈希ID。哈希ID似乎是随机的,但实际上是完整内容的加密校验和。这就是为什么不能更改提交-更改任何内容都会更改校验和,从而导致不同的提交。

    存储在提交中的文件也是只读的。它们以特殊的、仅限于Git的压缩形式存储。这种特殊的压缩具有一个好的属性,即如果一个文件的内容从一个提交到另一个提交相同,这些提交都共享底层压缩的文件映像。这意味着您可以提交一个大文件数百万次,如果您喜欢,而不使用比提交该文件一次更多的空间。

  • 索引/暂存区/缓存是这种几乎看不见的疯狂数据结构。它在所有时间都包含所有文件,就像提交包含所有文件一样。索引中的文件也以此特殊压缩的Git格式存在。索引/暂存区中的文件副本与提交中的副本之间的关键区别在于可以覆盖索引中的文件。

    (索引还缓存-因此称为“缓存”-有关工作树的信息,以使Git运行更快。这两个事实,即索引保存所有文件,准备进入下一个提交,并且缓存有关工作树的信息,是使 git commit 比其他类似版本控制系统快得多的原因)。

  • 工作树是三者中最简单的,但在某种意义上,Git对其关心最少。这是您在文件上进行工作的地方。这些文件采用其他计算机程序理解的普通格式。它们对您最重要,但对Git最不重要: --bare 存储库没有工作树,但Git仍然可以(当然是更有限的方式)运行。

    工作树是这三个事物中唯一一个您可以轻松直接看到的。只需使用列出文件或查看文件的任何命令:它们就在那里,很容易看到。幸运的是,通过检查它们,提交也很容易看到。 当你通过git checkout mastergit checkout develop等命令切换到某个特定的提交时,Git会从该提交中同时填充你的索引/暂存区和工作树。它会将HEAD设置为正确哈希ID的符号名称。这样,索引已经包含了与HEAD提交中相同的所有文件,而工作树中也有与索引中相同的所有文件。

    如果你修改了工作树中的文件,并且然后运行git add 命令,Git会将该文件的工作树版本复制到索引/暂存区。现在,HEAD提交的版本和索引版本不同,但是索引版本和工作树版本是一致的。
    如果你修改了工作树中的文件,但是没有运行git add命令,那么HEAD和索引版本是一致的,但是索引版本与工作树版本不一致。
    如果你修改了工作树中的文件,然后(1)使用git add命令将其复制到索引/暂存区,(2)再次修改它,则这个文件的三个版本都不同。这就是你看到的MM状态。 git status做的事情实际上就是运行两个差异。第一个比较HEAD和索引的差异。这里面任何不同的都是“已暂存以供提交”的。第二个比较索引和工作树的差异。这里面任何不同的都是“未暂存以供提交”的。这就是全部内容,我们快要完成了!
    最后,让我们来看看“已跟踪”这个术语在文件中的应用。在Git中,只有当文件在索引/暂存区中时它才被跟踪。实际上就是这么简单!难点在于判断文件是否实际上在索引中,因为通常它在那里是不可见的。 git status命令会比较索引:首先它会将HEADindex进行比较。假设某个文件既在HEAD中又在索引中,并且两者具有相同的内容,则你在这里不会看到它。同样,如果它在索引和工作树中是相同的,那么你也不会在这里看到它。所以,如果文件确实在索引中,但与HEAD和工作树版本都相匹配,则它是不可见的。
    假设某个文件不在索引中。如果它在HEAD中,git status会告诉你,在HEAD和索引之间,该文件被删除了——短输出的第一列是D。所以在这种情况下,你可以看出:文件已经从索引中消失,并且不再被跟踪。它不会在下一次提交中出现。
    假设某个文件不在HEAD中,但在索引中。在这种情况下,git status会告诉你,在HEAD和索引之间,该文件被添加了——短输出的第一列是A。所以在这种情况下,你可以看出该文件现在被跟踪,并将出现在下一次提交中。
    当一个文件既没有被跟踪又被忽略时,情况就变得棘手了,因为此时,如果该文件不在HEAD提交中(根据定义,它不在索引中——我们刚刚说过它没有被跟踪),第一列就不能告诉你任何信息:它不在这两个实体中,因此Git在这里不会有任何提示。如果该文件存在于工作区,第二列可以告诉你索引和工作树不匹配,但由于你告诉Git应该忽略未跟踪的工作树文件,git status也不会在这里提到它。
    最后,有几件值得一提的事情:
    - 你实际上可以查看索引。运行git ls-files --stage以快速查看大多数实际上在暂存区中的内容。这在一个大项目中是不切实际的,因为暂存区保存了每个文件的副本——也就是将要提交的每个文件。那可能有成千上万个文件。查看HEAD提交和索引/暂存区之间的差异更有用,所以这就是git status所做的(在--short输出的第一列中)。 - 你也可以直接查看提交的内容。运行git ls-tree -r HEAD以查看所有提交的文件。输出与git ls-files --stage类似。它添加了Git对象类型名称并取走了暂存号码,并使用树结构而不是索引的扁平树。与git ls-files --stage类似,这主要用于调试Git或编写新的高级命令,而不是用于常规工作。
    重点是,git status通过比较HEAD和索引,然后比较索引和工作树,总结了三个关键实体的状态。两列显示它们之间的差异,仅剥离字母代码和文件名。即使下一个提交将是此时索引/暂存区中的每个文件的快照,告诉你与当前快照或通过将工作树文件复制到索引中可能创建的快照相比有何不同仍更有用。
    1在Windows和MacOS上,打开名为readme.txt的文件会打开现有的名为README.TXT的文件(反之亦然),因此您可以使用小写字母,但Git在各种地方硬编码了全大写的HEAD字符串,所以最好坚持使用它。如果您不喜欢输入这么多,字符@HEAD的同义词。 2技术上,提交存储对象的哈希ID。树对象存储每个文件的名称、模式(100644或100755)和内容哈希ID,以及必要时子树的名称和哈希ID。因此,文件内容实际上并不在提交内部,而是作为blob对象放置在提交和树对象旁边。这是提交和索引共享blob对象的机制,因此无论您对大文件有多少快照,实际上您在存储库数据库中只有一个副本。

1
你可以在此处阅读有关这些字母代表的含义:

https://www.git-scm.com/docs/git-status#_short_format

如果“暂存区”、“已添加”或“未合并”对您来说不熟悉,那么您可能需要深入了解git。或者,只需停止使用-s标志,这样更容易理解。
Git专业版确实很棒,但您无法选择要阅读的内容。按正确的顺序阅读所有内容。https://git-scm.com/book/en/v2

我已经编辑了问题,以解释我困惑的内容。 - kanayt

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