使用以下方法之一:
git show -m c05f017
git show --first-parent c05f017
git diff c05f017^ c05f017
您的问题存在一个基本错误:提交不是差异;提交是快照。这似乎是一个没有区别的区别——对于某些提交,它是。但是对于合并提交,它不是 。
当git show(或git log -p)将提交显示为作为差异时,它通过将提交的快照与其他内容进行比较来做到这一点。 git diff 命令做同样的事情:它将一个提交与另一个提交进行比较。 (或者它可以将提交与工作树或索引的内容或其他一些组合进行比较。)
对于普通的提交,比较什么很明显:比较 this 提交的快照与 previous(即父级)提交的快照。这就是git show 所做的事情(还有git log -p):它从父提交运行git diff,到此提交。
不过,合并提交不只有一个父提交。他们有两个父母。1这就是他们首先“合并提交”的原因:合并提交的定义是至少有两个父母的提交。
1一个合并提交可以有三个或更多的父级。这些被称为“章鱼合并”。不过,他们并没有做任何特别的事情,主要是为了炫耀。 :-) 你可以在这里忽略它们。
当有两个父母时,git show 应该与哪一个比较?
git log -p 默认选择做的是根本不比较。您可以通过添加各种标志使其显示某些内容(见下文)。
git show 默认选择做什么比较复杂。由于有两个父母,git show 首先与“第一个父母”进行比较,2 然后与第二个父母进行比较。然后——这部分非常关键——它结合了两个差异,产生了所谓的“组合差异”。
在下一节中,让我注意一个棘手但非常有用的 Git 语法。如果你有一个像c05f017 这样的提交ID,你可以在之后添加一个插入符号或“帽子”字符^,来命名一个父提交。您可以选择添加另一个数字来选择 which 父级。对于常规(非合并)提交,只有一个,所以 c05f017^ 是 the 父级。对于合并提交,c05f017^ 和 c05f017^1 都表示第一个父节点,而c05f017^2 表示第二个父节点。
2我把它放在引号里是因为 first parent 的想法在 Git 中特别重要,我们稍后会看到。换句话说,Git 最关心的是哪个父级首先,而其余的只是“其余的”。
组合差异
组合的diff格式在the documentation中描述,但是在here中先描述了一个关键位,使其特别晦涩:3
请注意,combined diff 仅列出从所有父级修改的文件。
也就是说,假设 M 是一个合并提交,并且区分 M^1 与 M 表示文件 mainline.txt 和 common.txt都改变了。进一步假设区分 M^2 和 M 表示文件 sidebranch.txt 和 common.txt 都已更改。合并后的差异将仅显示common.txt,同时跳过mainline.txt 和sidebranch.txt,因为这两个文件仅从一个 父级(每个)修改。 (即使这样,Git 也可能只显示common.txt 的一些差异。)
3我花了很长时间才在文档中找到这个,因为我一直在查看其他部分。
拆分差异
-m 选项——m 在这里可能代表 merge——告诉 Git 实际上“拆分”合并。也就是说,与其尝试将每个父级的差异组合成一个大的组合差异,只需显示与 每个 父级的差异,一次一个差异。
这有时是你想要的。如果不是您想要的,您可以运行自己的显式 git diff 来区分两个父母之一(或见下文)。
您应该与哪个父母进行比较?
通常,正确答案是“第一父母”。
“第一父”概念的关键在于,当 Git 进行合并提交时,它总是将您当时所在的分支记录为第一父。另一个分支成为第二个父分支。
也就是说,如果您在 develop 上并合并 topic:
$ git checkout develop
$ git merge topic
Git 将在您当前的分支develop 上进行一个新的提交——一个合并提交,有两个父节点。合并提交的 first 父级将是刚才develop 的提示的提交。 second 父级将是(仍然)是topic 提示的提交。
由于您通常关心合并带来的内容,因此与第一个父项进行比较会给您带来好处。所以通常这就是你想要的。因此,git show 允许您运行git show --first-parent。这会“拆分”提交,然后 git show 仅与第一个父级不同。 (这与git show -m 有点不同,它将提交拆分两次:第一次拆分与第一个父项进行比较,第二次拆分与第二个父项进行比较。)
同样,你可以运行git log -p --first-parent 这里,--first-parent 标志有一个更重要的作用:日志操作根本不查看侧分支的提交,只查看那些在主(第一父)行上。请注意,如果您的 Git 早于 2.31,您仍然需要 -m 标志(使用 git log 时,即;git show 默认为 --cc,因此不需要 -m,并且所有这在 Git 2.31 中已被清理)。