如何 git 立即区分所有未(尚未)暂存的已修改文件?
How to git diff at once all modified files which are not (yet) staged?
git diff --staged
显示已有 staged
个文件的差异。
问题:如何 git diff
一次 modified
个尚未(尚未)暂存的文件?
例如:
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: f1.c
modified: f2.c
modified: f3.c
如何git diff
一次把所有modified
个文件都放在这里? IE。 git diff
立即 f1.c
, f2.c
, f3.c
.
与 in 一样,git diff
没有附加参数就已经这样做了。
不过,这里还有一些值得指出的地方。特别是,Git 在任何时候都有 1 三个 我称之为每个文件的“活动副本”。假设您在 当前 提交中拥有上述三个文件,以及名为 README.md
和 LICENSE.md
的文件。因此 当前提交中有五个文件:
README.md
LICENSE.md
f1.c
f2.c
f3.c
这五个文件是“活跃的”,因为它们位于 当前提交的 中,可供您与您现在正在做的事情进行比较,或者例如,使用 git reset --hard
将所有内容恢复到这五个文件中的状态。
同时,这五个文件已被复制到Git的索引中。2您不能看到这些副本,3但它们存在。事实上,它们是将进入您的 下一次提交 的副本。 git add
命令是关于 更新这些副本 ,它们最初与当前提交的副本相匹配。所以 Git 的索引中有相同的五个文件,直到你开始 运行ning git add
无论如何:复制新文件,取代以前的副本,或复制所有新文件进入 Git 的索引,例如添加第六个文件。
终于有五个文件的普通日常副本了。它们位于 Git 所谓的 working tree 或 work-tree 中。这些是你的,随心所欲:Git 将它们复制到 out 提交中——首先进入 Git的索引,然后进入你的工作树——当你 运行 git checkout
,4 从那时起,你可以随心所欲地使用它们。如果您已经 更改了 它们,并希望这些更新进入您的下一次提交,您将需要 运行 git add
,这将把更新复制回来进入 Git 的索引,更新索引副本以匹配您的工作树副本。
当你运行git status
时,这个命令:
- 打印出有用的信息,例如您所在的 b运行ch 名称,然后
- 运行一个对比:你看到的那个和
git diff --staged
;然后
- 运行再进行一次比较:您看到的带有
git diff
且没有额外选项的那个。
两个 git diff
是这里感兴趣的:
首先比较当前提交中的所有(在本例中为五个)文件——HEAD:README.md
、HEAD:LICENSE.md
,以及依此类推——Git 索引中的所有文件。当这两个文件 匹配 时,git status
什么也没说。当它们在某些方面 不同 时,git status
打印文件名,在类别 staged for commit
.
下
第二个 git diff
将 Git 索引中的所有文件与工作树中的所有同名文件进行比较。只要这两个相同,Git就什么都不说了;它们 不同 的地方说这个文件是 not staged for commit
.
请注意,三个副本可能各不相同。检查一些提交,以便所有五个(或任何计数)文件都相同。修改其中之一的副本,然后 运行 git add
。现在 HEAD
副本与其他两个不匹配,但 Git 的索引副本和您的副本匹配。但是现在修改你的再复制。所有三个文件现在都不同了,只要您的第二次更改不仅仅是将文件改回原样即可。 运行ning git status
现在会将一个文件显示为 both staged for commit
and not staged for commit
.
运行ning git diff --staged
5 比较 HEAD
与索引。 运行ning git diff
比较索引与工作树。 git diff
还有很多形式,例如 git diff <em>commit1 commit2</em>
。通读 the git diff
documentation 思考这个问题:如果你想比较 HEAD
提交与你当前的工作树,你应该 运行 什么,直接跳过索引位于它们之间的?(答案很简单,但在使用脚注 6 作弊之前,请尝试自己找到它。6)
1有时,Git 每个文件最多 五个 副本。特别是,在冲突合并期间,Git 将从三个提交中检索副本并将所有三个提交放入其索引中。很少——比如当你使用 git rm
删除一个文件时——这个数字会下降到三个以下,但随后我们就会陷入一个形而上学/哲学问题,这个问题属于“如果森林中没有文件,它是否创造了一个当你削减它时的噪音”之类的东西。
2这里有两点值得注意:
- Git 的索引还有两个名称:暂存区 和缓存。三者指的是同一件事。
- 索引中的内容实际上并不是每个文件的副本,而是模式、名称和 blob-hash 的三元组。这就是 Git 预压缩和预删除重复文件以进入提交或与某些现有提交共享文件的方式。
不过,这些东西 就像 文件的副本,因此将它们视为副本可能是最简单的。如果您开始使用脚注 3 中提到的命令,您将只能分辨出差异。
3你实际上可以看到它们,某种程度上。 运行 git ls-files --stage
转出索引内容。请注意,这会为每个暂存文件生成一行输出,包括 文件,git status
会静默跳过这些文件,因为它们已暂存但未修改。 “暂存中的文件 = 提交中的文件”情况是 为什么 git status
不 谈论文件。如果您正在处理一个包含数万个文件的大项目,您可能对 未更改的 29997 个文件不太感兴趣;您只关心 是 的 3 个文件。 运行 git ls-files
还好,它只看所有暂存文件,但当它输出30000行文件信息时,就没那么有用了。
git update-index
命令是一个类似的极低级命令,可让您直接操作文件的索引副本。由于这个确实写在索引上,所以在使用它的时候需要多加小心,但它确实有一些非常特殊的用途。
4Git 利用其索引中的内容来优化结帐。例如,假设您正在提交 a123456
,因为您 运行 git checkout main
或其他。然后你 运行 git checkout dev
选择提交 b789abc
来检出。在 Git 的索引和您的工作树中的 30000 个文件中,很有可能有 29735 个文件在这两个提交中 相同 ,只剩下 256 个不同 个文件。 checkout 命令可以将所有未更改的文件保留在 Git 的索引和您的工作树中,仅更新剩余的文件。这 快得多 。
对于我们这些习惯了旧版本控制系统的人来说,当我们第一次 运行 git checkout
并立即得到提示而不是五分钟的休息时,我们认为 Git坏了。这个索引的东西很聪明。不过,当您第一次习惯 Git 时,它确实会带来很长的路途。
5git diff --cached
和 git diff --staged
做完全一样的事情:--cached
和 --staged
在这里是同义词。 --cached
标志指的是索引的第三个名称,cache。 git rm --cached
中会出现相同的名称。由于某种原因,git rm
中仍然没有 --staged
同义词。 Git 这里的命令不是很一致,主要是历史原因。
6git diff HEAD
。 (现在,如果您想比较索引/暂存区中的内容与某些特定提交怎么办?)
git diff --staged
显示已有 staged
个文件的差异。
问题:如何 git diff
一次 modified
个尚未(尚未)暂存的文件?
例如:
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: f1.c
modified: f2.c
modified: f3.c
如何git diff
一次把所有modified
个文件都放在这里? IE。 git diff
立即 f1.c
, f2.c
, f3.c
.
与 git diff
没有附加参数就已经这样做了。
不过,这里还有一些值得指出的地方。特别是,Git 在任何时候都有 1 三个 我称之为每个文件的“活动副本”。假设您在 当前 提交中拥有上述三个文件,以及名为 README.md
和 LICENSE.md
的文件。因此 当前提交中有五个文件:
README.md
LICENSE.md
f1.c
f2.c
f3.c
这五个文件是“活跃的”,因为它们位于 当前提交的 中,可供您与您现在正在做的事情进行比较,或者例如,使用 git reset --hard
将所有内容恢复到这五个文件中的状态。
同时,这五个文件已被复制到Git的索引中。2您不能看到这些副本,3但它们存在。事实上,它们是将进入您的 下一次提交 的副本。 git add
命令是关于 更新这些副本 ,它们最初与当前提交的副本相匹配。所以 Git 的索引中有相同的五个文件,直到你开始 运行ning git add
无论如何:复制新文件,取代以前的副本,或复制所有新文件进入 Git 的索引,例如添加第六个文件。
终于有五个文件的普通日常副本了。它们位于 Git 所谓的 working tree 或 work-tree 中。这些是你的,随心所欲:Git 将它们复制到 out 提交中——首先进入 Git的索引,然后进入你的工作树——当你 运行 git checkout
,4 从那时起,你可以随心所欲地使用它们。如果您已经 更改了 它们,并希望这些更新进入您的下一次提交,您将需要 运行 git add
,这将把更新复制回来进入 Git 的索引,更新索引副本以匹配您的工作树副本。
当你运行git status
时,这个命令:
- 打印出有用的信息,例如您所在的 b运行ch 名称,然后
- 运行一个对比:你看到的那个和
git diff --staged
;然后 - 运行再进行一次比较:您看到的带有
git diff
且没有额外选项的那个。
两个 git diff
是这里感兴趣的:
首先比较当前提交中的所有(在本例中为五个)文件——
下HEAD:README.md
、HEAD:LICENSE.md
,以及依此类推——Git 索引中的所有文件。当这两个文件 匹配 时,git status
什么也没说。当它们在某些方面 不同 时,git status
打印文件名,在类别staged for commit
.第二个
git diff
将 Git 索引中的所有文件与工作树中的所有同名文件进行比较。只要这两个相同,Git就什么都不说了;它们 不同 的地方说这个文件是not staged for commit
.
请注意,三个副本可能各不相同。检查一些提交,以便所有五个(或任何计数)文件都相同。修改其中之一的副本,然后 运行 git add
。现在 HEAD
副本与其他两个不匹配,但 Git 的索引副本和您的副本匹配。但是现在修改你的再复制。所有三个文件现在都不同了,只要您的第二次更改不仅仅是将文件改回原样即可。 运行ning git status
现在会将一个文件显示为 both staged for commit
and not staged for commit
.
运行ning git diff --staged
5 比较 HEAD
与索引。 运行ning git diff
比较索引与工作树。 git diff
还有很多形式,例如 git diff <em>commit1 commit2</em>
。通读 the git diff
documentation 思考这个问题:如果你想比较 HEAD
提交与你当前的工作树,你应该 运行 什么,直接跳过索引位于它们之间的?(答案很简单,但在使用脚注 6 作弊之前,请尝试自己找到它。6)
1有时,Git 每个文件最多 五个 副本。特别是,在冲突合并期间,Git 将从三个提交中检索副本并将所有三个提交放入其索引中。很少——比如当你使用 git rm
删除一个文件时——这个数字会下降到三个以下,但随后我们就会陷入一个形而上学/哲学问题,这个问题属于“如果森林中没有文件,它是否创造了一个当你削减它时的噪音”之类的东西。
2这里有两点值得注意:
- Git 的索引还有两个名称:暂存区 和缓存。三者指的是同一件事。
- 索引中的内容实际上并不是每个文件的副本,而是模式、名称和 blob-hash 的三元组。这就是 Git 预压缩和预删除重复文件以进入提交或与某些现有提交共享文件的方式。
不过,这些东西 就像 文件的副本,因此将它们视为副本可能是最简单的。如果您开始使用脚注 3 中提到的命令,您将只能分辨出差异。
3你实际上可以看到它们,某种程度上。 运行 git ls-files --stage
转出索引内容。请注意,这会为每个暂存文件生成一行输出,包括 文件,git status
会静默跳过这些文件,因为它们已暂存但未修改。 “暂存中的文件 = 提交中的文件”情况是 为什么 git status
不 谈论文件。如果您正在处理一个包含数万个文件的大项目,您可能对 未更改的 29997 个文件不太感兴趣;您只关心 是 的 3 个文件。 运行 git ls-files
还好,它只看所有暂存文件,但当它输出30000行文件信息时,就没那么有用了。
git update-index
命令是一个类似的极低级命令,可让您直接操作文件的索引副本。由于这个确实写在索引上,所以在使用它的时候需要多加小心,但它确实有一些非常特殊的用途。
4Git 利用其索引中的内容来优化结帐。例如,假设您正在提交 a123456
,因为您 运行 git checkout main
或其他。然后你 运行 git checkout dev
选择提交 b789abc
来检出。在 Git 的索引和您的工作树中的 30000 个文件中,很有可能有 29735 个文件在这两个提交中 相同 ,只剩下 256 个不同 个文件。 checkout 命令可以将所有未更改的文件保留在 Git 的索引和您的工作树中,仅更新剩余的文件。这 快得多 。
对于我们这些习惯了旧版本控制系统的人来说,当我们第一次 运行 git checkout
并立即得到提示而不是五分钟的休息时,我们认为 Git坏了。这个索引的东西很聪明。不过,当您第一次习惯 Git 时,它确实会带来很长的路途。
5git diff --cached
和 git diff --staged
做完全一样的事情:--cached
和 --staged
在这里是同义词。 --cached
标志指的是索引的第三个名称,cache。 git rm --cached
中会出现相同的名称。由于某种原因,git rm
中仍然没有 --staged
同义词。 Git 这里的命令不是很一致,主要是历史原因。
6git diff HEAD
。 (现在,如果您想比较索引/暂存区中的内容与某些特定提交怎么办?)