$ git status -s
M README
MM Rakefile
A lib/git.rb
M lib/simplegit.rb
?? LICENSE.txt
Run Code Online (Sandbox Code Playgroud)
输出有两列 - 左侧列表示暂存区的状态,右侧列表示工作树的状态。例如,在该输出中,工作目录中的 README 文件已修改但尚未暂存,而 lib/simplegit.rb 文件已修改并暂存。Rakefile 被修改、暂存,然后再次修改,因此对它进行了暂存和未暂存的更改。
以上来自 Pro Git,作者是 Scott Chacon 和 Ben Straub,由 Apress 出版。
我对暂存区和工作树之间的区别感到困惑。我会解释我认为是真实的。
“自述文件已在工作目录中修改但尚未暂存”:我们没有跟踪此文件。尽管如此,Git 知道它已被修改。从最后一个快照。
“lib/simplegit.rb 文件被修改并暂存”:修改后我们已经暂存了文件。剩下的就是提交。
“Rakefile 被修改,暂存,然后再次修改,因此它的更改既有暂存的,也有未暂存的。”:就像之前的文件一样,我们暂存了一个修改过的文件。下一步是什么?
“自述文件已在工作目录中修改但尚未暂存”:我们没有跟踪此文件。尽管如此,Git 知道它已被修改。从最后一个快照。
不,这是错误的。临时区域的棘手部分是它通常是不可见的。这导致人们在试图理解它是如何工作的过程中走上了错误的道路。
首先,让我们处理一些 Git 术语。此时有三个感兴趣的实体:当前提交、暂存区(实际上有三个名称)和工作树。staging-area 的三个名称是index、staging-area和cache,这三个名称反映了 Linus Torvald 原始选择(“index”)的低质量或不可见 staging-area 的巨大重要性,或两者兼而有之。(我认为两者都有。)让我们更深入地了解每一个:
当前提交,我们也可以通过名称HEAD(全部大写1)命名,当然是一次提交——它是您(或任何人)运行 时位于暂存区的所有文件的快照git commit。此快照是永久性的(大部分)和只读的(完全)。它的真名不是HEAD——这只是一个我们现在可以通过它找到的象征性名称——而是一些丑陋的大哈希ID。哈希 ID 看起来是随机的,但实际上是提交完整内容的加密校验和。这就是无法更改提交的原因——更改任何内容都会更改校验和,从而导致不同的提交。
2提交中存储的文件也是只读的。它们以一种特殊的、仅限 Git 的压缩形式存储。这种特殊的压缩有一个很好的特性,如果一个文件的内容从一个提交到另一个提交是相同的,那么这些提交都共享底层的压缩文件映像。这意味着您可以提交一个大文件数百万次,如果您愿意,并且不会使用比提交该文件更多的空间。
索引/暂存区/缓存是这种疯狂的几乎不可见的数据结构。它始终包含所有文件,就像提交包含所有文件一样。索引中的文件也是这种特殊的压缩 Git 格式。索引/暂存区中的文件副本与提交中的副本之间的主要区别在于索引可以被覆盖。
(索引还缓存——因此名称为“缓存”——关于工作树的信息,以使 Git 运行得更快。这两个事实,即索引保存所有准备好进入下一次提交的文件,并且它缓存git commit与其他类似的版本控制系统相比,关于工作树的东西是非常快的。)
工作树是三者中最简单的,但从某种意义上说,也是 Git 最不关心的一个。这是您处理文件的地方。这些文件采用其他计算机程序可以理解的普通格式。它们对你最重要,但对 Git 最不重要:--bare存储库没有工作树,但 Git 仍然可以运行(当然以更有限的方式)。
工作树是这三件事中唯一可以轻松直接看到的。只需使用列出文件或查看文件的任何命令:它们就在那里,一目了然。幸运的是,提交也很容易看到,通过检查它们。
当您最初检查出一些特定的承诺-通过git checkout master或者git checkout develop,例如,Git的填充两种索引/舞台区和你的工作树从提交。它设置HEAD为正确哈希 ID 的符号名称。这样,索引中已经包含HEAD提交中的所有相同文件,并且工作树中包含索引中的所有相同文件。
如果您修改工作树中的文件,然后git add在其上运行,Git 会将该文件的工作树版本复制到索引/暂存区。现在HEAD提交版本和索引版本不同,但索引版本和工作树版本一致。
如果你修改了工作树中的一个文件但没有git add在它上面运行,则HEAD索引版本和索引版本一致,但索引版本与工作树版本不一致。
如果您修改工作树中的文件,则 (1) 使用git add将其复制到索引/暂存区和 (2)再次修改它,现在该文件的所有三个版本都不同。您将在此处看到MM状态。
什么git status是做的是,在效果上运行两个差异列表。第一个与HEAD索引进行比较。这里的不同之处是“为提交而上演”。第二个差异将索引与工作树进行比较。这里的不同之处是“不为提交而上演”。这几乎是它-我们几乎完成了!
最后,让我们看一下应用于文件的术语跟踪。在 Git 中,当且仅当文件在索引/暂存区中时才会被跟踪。真的就是这么简单!棘手的部分是判断文件是否确实在索引中,因为它通常在那里不可见。
该git status命令比较索引:首先,它比较HEADvs index。假设某个文件在两者中HEAD并且在两者中index具有相同的内容。那你就看不到这里了。同样,如果它在索引和工作树中相同,您将不会在此处看到它。因此,如果该文件是在索引中,但同时匹配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 对象的机制,因此无论您拥有多少个大文件的快照,您在存储库数据库中实际上只有一个副本。
| 归档时间: |
|
| 查看次数: |
2414 次 |
| 最近记录: |