使用short标志了解git status的输出

时间:2018-07-06 12:55:59

标签: git terminology

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

输出有两列-左列指示临时区域的状态,右列指示工作树的状态。因此,例如在该输出中,自述文件在工作目录中被修改但尚未暂存,而lib / simplegit.rb文件已被修改并暂存。 Rakefile已被修改,暂存,然后再次被修改,因此它具有暂存和未暂存的更改。

以上内容来自Scott Chacon和Ben Straub的Pro Git,由Apress发布。

我对暂存区和工作树之间的区别感到困惑。我会解释我认为是真实的。

“自述文件已在工作目录中修改,但尚未暂存”:我们未跟踪此文件。不过,Git知道它已被修改。从上一个快照开始。

“ lib / simplegit.rb文件已修改并暂存”:修改后,我们暂存了文件。剩下的就是提交。

“ Rakefile已被修改,暂存,然后再次被修改,因此对其进行了暂存和未暂存的更改。”:就像先前的文件一样,我们暂存了已修改的文件。接下来是什么?

2 个答案:

答案 0 :(得分:2)

  

“自述文件已在工作目录中修改,但尚未暂存”:我们未跟踪此文件。不过,Git知道它已被修改。从上一个快照开始。

不,这是错误的。临时区域的棘手部分是通常通常是不可见的。这会导致人们在尝试理解其工作原理时走错了路。

首先,让我们讨论一些Git术语。这时有三个感兴趣的实体:当前提交临时区域(实际上有三个名称)和工作树。临时区域的三个名称是 index 临时区域 cache ,这三个名称反映了Linus Torvald的低质量原始选择(“索引”)或不可见的暂存区域的巨大重要性,或两者兼而有之。 (我认为两者都可以。)让我们更深入地研究每一个:

  • 当前提交,我们也可以通过名称HEAD来命名(使用大写字母 1 ),它当然是一次提交-它是所有文件的快照您(或任何人)运行git commit时在登台区域中的文件。该快照是永久的(大部分),只读的(全部)。它的真实名称不是HEAD(这只是我们现在可以通过它找到的符号名称),而是一些大的丑陋的哈希ID。哈希ID看起来是随机的,但实际上是提交的完整内容的加密校验和。这就是为什么为什么不能更改提交-更改任何内容都会更改校验和,从而导致不同提交。

    2 提交中存储的文件也是只读的。它们以特殊的,仅Git的压缩形式存储。这种特殊的压缩具有很好的特性,即如果文件的内容从一次提交到另一次提交都是相同的,则这些文件将全部 share 提交到基础的压缩文件映像中。这意味着您可以根据需要提交一个大文件数百万次,并且使用的空间不会比一次提交该文件多。

  • 索引/分段区域/缓存是这种疯狂的几乎不可见的数据结构。它始终包含所有文件,就像提交包含所有文件一样。索引中的文件也采用这种特殊的压缩Git-only格式。索引/暂存区中的文件副本与提交中的副本之间的主要区别在于,索引之一可以被覆盖

    (索引还缓存(因此名为“ cache”)有关工作树的信息,以使Git更快运行。这两个事实是,索引保存了所有准备好进入下一次提交的文件,并且与其他类似的版本控制系统相比,它可以使git commit如此之快地超速运行。)

  • 工作树是这三个中最简单的树,但是从某种意义上说,Git最不关心它。在这里您可以处理文件。这些文件是其余计算机程序可以理解的普通格式。它们对 you 最重要,但对Git则最不重要:--bare存储库没有 工作树,但是Git仍然可以工作(在当然更有限的方式。)

工作树是您可以轻松直接看到的三件事中的唯一一件事。只需使用列出文件或视图文件的任何命令:就可以看到它们。幸运的是,通过检出提交,提交也很容易看到。

例如,当您最初通过git checkout mastergit checkout develop签出某些特定的提交时,Git会同时为您的索引/临时区域填充 em>您从该提交开始工作。它将HEAD设置为正确哈希ID的符号名称。这样,索引中已经包含了HEAD提交中的所有相同文件,而工作树具有了索引中的所有相同文件。

如果您修改工作树中的文件,然后在其上运行git add,则Git会将该文件的工作树版本复制到索引/暂存区中。现在,HEAD提交版本和索引版本不同,但是索引版本和工作树版本彼此一致。

如果您修改工作树中的文件,但不要在其上运行git add,则HEAD和索引版本会一致,但是索引版本会与工作树版本。

如果您在工作树中修改文件,则(1)使用git add将其复制到索引/暂存区,然后(2)再次修改 该文件的所有三个版本都不同。在这里您将看到MM状态。

git status的作用实际上是运行两个diff。第一个将HEAD与索引进行比较。这里有什么不同是“上演提交”。第二个差异将索引与工作树进行比较。这里有什么不同,就是“不上演提交”。差不多了-我们快完成了!

最后,让我们看看应用于文件的术语 tracked 。在Git中,仅当文件位于索引/暂存区域中时,才会跟踪文件。真的就是这么简单!棘手的部分是告诉文件实际上是否在索引中,因为它在那里通常是不可见的。

git status命令比较索引:首先,它比较HEADindex。假设某个文件同时位于HEADindex中,并且两者都具有相同的内容。那么您在这里看不到它。同样,如果索引和工作树中的相同,您将在这里看不到它。因此,如果文件在索引中,但同时与HEAD和工作树版本都匹配,则它是不可见的。

假设索引中没有文件 。如果在HEAD中,则git status会告诉您在HEAD和索引之间,文件已删除—在简短输出的第一列中是D。因此,在这种情况下,您可以知道:文件已离开索引,不再被跟踪。它不会在下一次提交中。

假设HEAD中的某些文件不是,但是索引中的。在这种情况下,git status会告诉您在HEAD和索引之间,文件被添加了-在简短输出的第一列中为A。因此,在这种情况下,您可以确定该文件现在已被跟踪,并且将在下一次提交中。

棘手的情况发生在文件没有被跟踪和忽略的情况下,因为现在,如果在HEAD提交中文件是 not (根据定义)它不在索引中(我们只是说它是未跟踪的),第一列什么也不能告诉您:它不在这两个实体中的任何一个中,因此Git在这里什么也没说。第二列可以告诉您,如果文件在工作树中存在,则索引和工作树不匹配,但是由于您告诉Git应该忽略未跟踪的工作树文件,git status在这里也不会提及。

最后,有几件事值得一提:

  • 可以实际查看索引。运行git ls-files --stage,以快速查看暂存区中实际的大部分内容。在大型项目中,这是不切实际的,恰好是因为暂存区拥有每个文件的副本-嗯,每个要提交的文件。那可能是成千上万的文件。查看HEAD提交与索引/分段区域之间的差异有用得多,这就是git status的作用(在{{1}的第一列中}输出)。

  • 您还可以直接查看提交的内容。运行--short以查看所有已提交的文件。输出类似于git ls-tree -r HEAD。 (它添加了Git对象类型名称,并删除了阶段号,并使用树结构而不是索引的flattened-tree。)与git ls-files --stage一样,这主要用于调试Git或编写新的漂亮命令,而不是进行日常工作。

此处的关键在于,git ls-files --stage通过将git status与索引进行比较,然后将索引与工作树进行比较,来概括感兴趣的三个实体的状态。这两列显示了它们之间的差异,并简化为字母代码和文件名。即使下一次提交将是当时索引/暂存区域中每个文件的快照,但告诉您与当前快照相比,该快照的差异更为有用,或您将工作树文件复制到索引中可以制作的潜在快照。


1 在Windows和MacOS上,打开名为HEAD的文件会打开一个名为readme.txt的现有文件(反之亦然),您可以使用小写字母,但是Git有多种硬编码全大写README.TXT字符串的位置,因此最好坚持使用。如果您不喜欢输入太多,则字符HEAD@的同义词。

2 从技术上讲,提交存储 tree 对象的哈希ID。树对象存储每个文件的名称,模式(100644或100755)和content-hash-ID,以及根据需要的子树的名称和哈希ID。因此,文件内容实际上不在提交中 内,而是布置为 blob 对象,与提交和树对象并排放置。这是提交(和索引!)共享blob对象的机制,因此无论您拥有一个大文件的快照多少,存储库数据库中实际上只有一个副本。

答案 1 :(得分:1)

您可以在此处了解字母的含义:

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

如果您不熟悉“临时区域”,“添加的”或“未合并的”,也许您需要加深对git的理解。或者也许只是停止使用-s标志,这真的很容易理解。

git pro git实际上是git,但是您无法选择要阅读的内容。以正确的顺序阅读所有内容。 https://git-scm.com/book/en/v2