使用短标志了解 git 状态的输出
Understanding the output of git status with the short flag
$ 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 的 Pro Git,由 Apress 出版。
我对暂存区和工作树之间的区别感到困惑。我会解释我认为是真实的。
"the README file is modified in the working directory but not yet staged":我们没有跟踪这个文件。尽管如此,Git 明白它已被修改。来自上一个快照。
"the lib/simplegit.rb file is modified and staged":修改后我们已经暂存了文件。剩下的就是提交。
"The Rakefile was modified, staged and then modified again, so there are changes to it that are both staged and unstaged.":就像之前的文件一样,我们暂存了一个修改后的文件。接下来是什么?
您可以在此处了解这些字母的含义:
https://www.git-scm.com/docs/git-status#_short_format
如果"staging area"、"added"或"unmerged"对您来说比较陌生,也许您需要加深对git的理解。或者也许只是停止使用 -s
标志,这真的更容易理解。
git亲git确实是git,但是不能挑自己想看的。以正确的顺序阅读所有内容。 https://git-scm.com/book/en/v2
"the README file is modified in the working directory but not yet staged": We're not tracking this file. Still, Git understands that it has been modified. From the last snapshot.
不,这是错误的。暂存区的棘手部分是它通常大部分是不可见的。这导致人们在试图理解其工作原理时走上了错误的道路。
首先,让我们处理一些 Git 术语。此时有三个感兴趣的实体:current commit、staging-area——实际上有三个名字——以及工作树。 staging-area 的三个名称是 index、staging-area 和 cache,这些三个名称反映了 Linus Torvald 最初选择(“索引”)的低质量或不可见的临时区域的巨大重要性,或两者兼而有之。 (我认为两者都有。)让我们更深入地了解每一个:
当前提交,我们也可以通过名称HEAD
(全部大写1)来命名,当然是一个提交——它是您(或任何人)运行 git commit
时暂存区中所有文件的快照。此快照是永久的(大部分)和只读的(完全)。它的真实名称不是 HEAD
——这只是一个符号名称,我们现在可以通过它找到它——而是一些丑陋的大哈希 ID。哈希 ID 显示为 运行dom,但实际上是提交完整内容的加密校验和。这就是 为什么 无法更改提交——更改任何内容都会更改校验和,从而导致 不同的 提交。
2 提交中存储的文件也是只读的。它们以特殊的、仅 Git 的压缩形式存储。这种特殊的压缩有一个很好的 属性 如果一个文件的内容从一个提交到另一个是相同的,这些提交所有 share 底层压缩文件图像。这意味着您可以提交一个大文件数百万次,如果您愿意的话,并且不使用 space 比提交该文件一次更多。
索引/暂存区/缓存是这种疯狂的几乎不可见的数据结构。它始终包含[=106=]所有文件,就像一次提交包含所有文件一样。索引中的文件也是这种特殊的压缩格式 Git-only。索引/暂存区中的文件副本与提交中的副本之间的主要区别在于索引可以 overwritten.
(索引还缓存——因此得名“缓存”——有关工作树的信息,以使 Git 运行得更快。这两个事实,即索引保存所有准备就绪的文件进入下一次提交,并且它缓存了关于工作树的东西,这使得 git commit
与其他类似的版本控制系统相比速度如此之快。)
工作树是三者中最简单的,但从某种意义上说,也是 Git 最不关心的。这是您处理文件的地方。这些文件采用您的其他计算机程序可以理解的普通格式。它们对 you 最重要,但对 Git 最不重要:--bare
存储库 no work-树,但 Git 仍然可以运行(当然以更有限的方式)。
工作树是这三件事中唯一您可以轻松直接看到的。只需使用列出文件或查看文件的任何命令:它们就在那里,一目了然。幸运的是,通过签出提交也很容易看到。
当你最初检查一些特定的提交时——例如,通过 git checkout master
或 git checkout develop
——Git 填充 both 你的索引 /暂存区 and 您来自该提交的工作树。它将 HEAD
设置为正确哈希 ID 的符号名称。这样,索引中已经包含 HEAD
提交中的所有相同文件,并且工作树中包含索引中的所有相同文件。
如果您修改工作树中的文件,然后 运行 git add
在其上,Git 将该文件的工作树版本复制到索引/暂存中-区域。现在 HEAD
提交版本和索引版本不同,但索引版本和工作树版本一致。
如果您修改了工作树中的文件但不 运行 git add
,HEAD
和索引版本一致,但索引版本与工作树版本不一致。
如果您修改工作树中的文件,则 (1) 使用 git add
将其复制到索引/暂存区并 (2) 再次修改它 ,现在 该文件的所有三个 版本都不同。在这里您会看到 MM
状态。
git status
所做的实际上是 运行宁两个差异。第一个将 HEAD
与索引进行比较。这里的任何不同之处都是“提交提交”。第二个差异将索引与工作树进行比较。这里的不同之处在于“不为提交而准备”。 差不多了——我们快完成了!
最后,让我们看一下术语 tracked 应用于文件。在 Git 中,当且仅当文件位于索引/暂存区中时,该文件才会被跟踪。真的就这么简单!棘手的部分是判断一个文件是否确实在索引中,因为它通常在那里是不可见的。
git status
命令比较索引:首先,它比较HEAD
与index
。假设某个文件在 HEAD
和 index
中,并且两者的内容相同。那么你不会在这里看到它。同样,如果它在索引和工作树中相同,您将不会在此处看到它。因此,如果索引中的文件 是 ,但同时匹配 HEAD
和工作树版本,则它是不可见的。
假设某些文件 不在 中。如果它在 HEAD
中,git status
会告诉您在 HEAD
和索引之间,文件被删除了——短输出第一列中的 D
。所以在那种情况下你可以知道:文件已经离开索引,并且不再被跟踪。它不会在下一次提交中。
假设某些文件 不在 HEAD
中 ,但索引中 是 。在这种情况下,git status
会告诉您在 HEAD
和索引之间,文件得到了 添加 — 短的第一列中的 A
输出。所以在这种情况下,您可以知道该文件现在已被跟踪,并将在下一次提交中。
棘手的情况发生在文件 既未被跟踪又被忽略,因为现在,如果文件 不 在 HEAD
提交(根据定义,它不在索引中——我们只是说它未被跟踪),第一列不能告诉你任何信息:它不在这两个实体中的任何一个中,所以 Git 在这里什么也没说.第二列 可以 告诉您索引和工作树不匹配,如果文件存在于工作树中,但是因为您告诉 Git 未跟踪work-tree文件应该忽略,git status
这里也不提了。
最后,有几点值得一提:
您可以实际查看索引。 运行 git ls-files --stage
快速查看暂存区中的大部分内容。这在大项目中是不切实际的,正是因为暂存区保存了 每个 文件的副本——好吧,每个将要提交的文件。那可能是数以万计的文件。查看 HEAD
提交和索引/暂存区之间的 差异 更有用,所以这就是 git status
所做的(在 [的第一列中) =46=] 输出).
您还可以直接查看提交的内容。 运行 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从技术上讲,提交存储 tree 对象的哈希 ID。树对象存储每个文件的名称、模式(100644 或 100755)和内容哈希 ID,以及所需的子树的名称和哈希 ID。因此,文件内容实际上并不是 inside 提交,而是布置为 blob 对象,与提交和树对象并排放置。这是提交和索引!共享 blob 对象的机制,因此无论您拥有一个大文件的多少快照,您在存储库数据库中实际上只有一个副本。
$ 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 的 Pro Git,由 Apress 出版。
我对暂存区和工作树之间的区别感到困惑。我会解释我认为是真实的。
"the README file is modified in the working directory but not yet staged":我们没有跟踪这个文件。尽管如此,Git 明白它已被修改。来自上一个快照。
"the lib/simplegit.rb file is modified and staged":修改后我们已经暂存了文件。剩下的就是提交。
"The Rakefile was modified, staged and then modified again, so there are changes to it that are both staged and unstaged.":就像之前的文件一样,我们暂存了一个修改后的文件。接下来是什么?
您可以在此处了解这些字母的含义:
https://www.git-scm.com/docs/git-status#_short_format
如果"staging area"、"added"或"unmerged"对您来说比较陌生,也许您需要加深对git的理解。或者也许只是停止使用 -s
标志,这真的更容易理解。
git亲git确实是git,但是不能挑自己想看的。以正确的顺序阅读所有内容。 https://git-scm.com/book/en/v2
"the README file is modified in the working directory but not yet staged": We're not tracking this file. Still, Git understands that it has been modified. From the last snapshot.
不,这是错误的。暂存区的棘手部分是它通常大部分是不可见的。这导致人们在试图理解其工作原理时走上了错误的道路。
首先,让我们处理一些 Git 术语。此时有三个感兴趣的实体:current commit、staging-area——实际上有三个名字——以及工作树。 staging-area 的三个名称是 index、staging-area 和 cache,这些三个名称反映了 Linus Torvald 最初选择(“索引”)的低质量或不可见的临时区域的巨大重要性,或两者兼而有之。 (我认为两者都有。)让我们更深入地了解每一个:
当前提交,我们也可以通过名称
HEAD
(全部大写1)来命名,当然是一个提交——它是您(或任何人)运行git commit
时暂存区中所有文件的快照。此快照是永久的(大部分)和只读的(完全)。它的真实名称不是HEAD
——这只是一个符号名称,我们现在可以通过它找到它——而是一些丑陋的大哈希 ID。哈希 ID 显示为 运行dom,但实际上是提交完整内容的加密校验和。这就是 为什么 无法更改提交——更改任何内容都会更改校验和,从而导致 不同的 提交。2 提交中存储的文件也是只读的。它们以特殊的、仅 Git 的压缩形式存储。这种特殊的压缩有一个很好的 属性 如果一个文件的内容从一个提交到另一个是相同的,这些提交所有 share 底层压缩文件图像。这意味着您可以提交一个大文件数百万次,如果您愿意的话,并且不使用 space 比提交该文件一次更多。
索引/暂存区/缓存是这种疯狂的几乎不可见的数据结构。它始终包含[=106=]所有文件,就像一次提交包含所有文件一样。索引中的文件也是这种特殊的压缩格式 Git-only。索引/暂存区中的文件副本与提交中的副本之间的主要区别在于索引可以 overwritten.
(索引还缓存——因此得名“缓存”——有关工作树的信息,以使 Git 运行得更快。这两个事实,即索引保存所有准备就绪的文件进入下一次提交,并且它缓存了关于工作树的东西,这使得
git commit
与其他类似的版本控制系统相比速度如此之快。)工作树是三者中最简单的,但从某种意义上说,也是 Git 最不关心的。这是您处理文件的地方。这些文件采用您的其他计算机程序可以理解的普通格式。它们对 you 最重要,但对 Git 最不重要:
--bare
存储库 no work-树,但 Git 仍然可以运行(当然以更有限的方式)。
工作树是这三件事中唯一您可以轻松直接看到的。只需使用列出文件或查看文件的任何命令:它们就在那里,一目了然。幸运的是,通过签出提交也很容易看到。
当你最初检查一些特定的提交时——例如,通过 git checkout master
或 git checkout develop
——Git 填充 both 你的索引 /暂存区 and 您来自该提交的工作树。它将 HEAD
设置为正确哈希 ID 的符号名称。这样,索引中已经包含 HEAD
提交中的所有相同文件,并且工作树中包含索引中的所有相同文件。
如果您修改工作树中的文件,然后 运行 git add
在其上,Git 将该文件的工作树版本复制到索引/暂存中-区域。现在 HEAD
提交版本和索引版本不同,但索引版本和工作树版本一致。
如果您修改了工作树中的文件但不 运行 git add
,HEAD
和索引版本一致,但索引版本与工作树版本不一致。
如果您修改工作树中的文件,则 (1) 使用 git add
将其复制到索引/暂存区并 (2) 再次修改它 ,现在 该文件的所有三个 版本都不同。在这里您会看到 MM
状态。
git status
所做的实际上是 运行宁两个差异。第一个将 HEAD
与索引进行比较。这里的任何不同之处都是“提交提交”。第二个差异将索引与工作树进行比较。这里的不同之处在于“不为提交而准备”。 差不多了——我们快完成了!
最后,让我们看一下术语 tracked 应用于文件。在 Git 中,当且仅当文件位于索引/暂存区中时,该文件才会被跟踪。真的就这么简单!棘手的部分是判断一个文件是否确实在索引中,因为它通常在那里是不可见的。
git status
命令比较索引:首先,它比较HEAD
与index
。假设某个文件在 HEAD
和 index
中,并且两者的内容相同。那么你不会在这里看到它。同样,如果它在索引和工作树中相同,您将不会在此处看到它。因此,如果索引中的文件 是 ,但同时匹配 HEAD
和工作树版本,则它是不可见的。
假设某些文件 不在 中。如果它在 HEAD
中,git status
会告诉您在 HEAD
和索引之间,文件被删除了——短输出第一列中的 D
。所以在那种情况下你可以知道:文件已经离开索引,并且不再被跟踪。它不会在下一次提交中。
假设某些文件 不在 HEAD
中 ,但索引中 是 。在这种情况下,git status
会告诉您在 HEAD
和索引之间,文件得到了 添加 — 短的第一列中的 A
输出。所以在这种情况下,您可以知道该文件现在已被跟踪,并将在下一次提交中。
棘手的情况发生在文件 既未被跟踪又被忽略,因为现在,如果文件 不 在 HEAD
提交(根据定义,它不在索引中——我们只是说它未被跟踪),第一列不能告诉你任何信息:它不在这两个实体中的任何一个中,所以 Git 在这里什么也没说.第二列 可以 告诉您索引和工作树不匹配,如果文件存在于工作树中,但是因为您告诉 Git 未跟踪work-tree文件应该忽略,git status
这里也不提了。
最后,有几点值得一提:
您可以实际查看索引。 运行
git ls-files --stage
快速查看暂存区中的大部分内容。这在大项目中是不切实际的,正是因为暂存区保存了 每个 文件的副本——好吧,每个将要提交的文件。那可能是数以万计的文件。查看HEAD
提交和索引/暂存区之间的 差异 更有用,所以这就是git status
所做的(在 [的第一列中) =46=] 输出).您还可以直接查看提交的内容。 运行
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从技术上讲,提交存储 tree 对象的哈希 ID。树对象存储每个文件的名称、模式(100644 或 100755)和内容哈希 ID,以及所需的子树的名称和哈希 ID。因此,文件内容实际上并不是 inside 提交,而是布置为 blob 对象,与提交和树对象并排放置。这是提交和索引!共享 blob 对象的机制,因此无论您拥有一个大文件的多少快照,您在存储库数据库中实际上只有一个副本。