git log -p在默认情况下根本不进行比较,您可以通过添加各种标志(见下文)使其显示某些内容。 git show在默认情况下选择做的事情更复杂。由于有两个父节点,git show首先与“第一个父节点”进行比较,2然后与第二个父节点进行比较。然后-这部分非常关键-它组合两个差异,产生所谓的“组合差异”。 在下一节中,让我注意一个棘手但非常有用的Git语法。如果你有一个像c05f017这样的提交ID,你可以在后面添加一个插入符号或“帽子”字符^,来命名一个父提交。你可以选择添加另一个数字来选择 which parent。对于常规的(non-merge)commits只有一个,所以c05f017^是 the parent。对于merge commits,c05f017^和c05f017^1都表示 the first parent,而c05f017^2表示 the second parent。 2我把这句话放在引号里是因为 first parent 这个概念在Git中特别重要,我们一会儿就会看到。换句话说,Git最关心的是哪个父节点是 first,而其余的只是“其余的”。
组合差异
文档中描述了组合的diff格式,但这里首先描述了一个关键位,以便使其特别模糊:3 请注意,combined diff 仅列出从所有父代修改的文件。 也就是说,假设 M 是一个合并提交,并且diff M^1 vs M 表示文件mainline.txt和common.txt都被更改。进一步假设diff M^2 和 M 表示文件sidebranch.txt和common.txt都被更改。组合的diff将显示 *only common.txt *,跳过mainline.txt和sidebranch.txt,因为这两个文件只修改了 * 一个 * 父文件(每个)。(即使这样,Git也可能只显示common.txt的一些差异。) 3我花了很长时间才在文档中找到这一点,因为我一直在看其他部分。
区分
-m选项-m 在这里可能代表 merge-告诉Git实际上“拆分”合并。也就是说,不要试图将每个父节点的差异组合成一个大的组合差异,而只是显示 each 父节点的差异,一次一个差异。 有时候这是你想要的,但如果不是你想要的,你可以运行你自己的git diff来比较两个父类中的一个(或者见下文)。
git show -c c0f501将显示提交c0f501到其双亲的组合差异,如git diff在合并期间打印的。 这给出了比git show -m更好的概述。 但是,它只显示相对于双亲更改的文件中的更改(或至少两个用于octopus合并的父节点)。例如,当文件f1和f2在第一个父节点上被改变,而f2和f3在第二个父节点上被改变时,这个命令只会显示f2中的更改。f1和f3中的更改 * 不会 * 显示。因此,为了获得完整的概述,在使用git show -c之前或之后使用git show -m仍然是有意义的。 以下是一个octopus合并的git show -c输出示例,其中包含两个文件中的更改,其中只有一个文件针对多个父文件进行了更改:
commit 3a9f99582921495f7c25e682d4af36d3407983f9 (HEAD -> master)
Merge: 33fb507 91c772b edf2d9c
Author: Foo Bar <foobar@example.net>
Date: Mon Mar 22 15:56:37 2021 +0100
Merge branches 'b1' and 'b2'
diff --combined b
index 4658c0c,a305e3c,2788b76..9c7beb1
--- a/b
+++ b/b
@@@@ -1,5 -1,5 -1,5 +1,7 @@@@
1
2
+ +a
3
++b
4
++ c
--diff-merges=(off|none|on|first-parent|1|separate|m|combined|c|dense-combined|cc|remerge|r), --no-diff-merges
Specify diff format to be used for merge commits.
Default is dense-combined unless --first-parent is in use, in which case first-parent is the default.
--diff-merges=(off|none), --no-diff-merges
Disable output of diffs for merge commits. Useful to override implied value.
--diff-merges=on, --diff-merges=m, -m
This option makes diff output for merge commits to be shown in the default format.
-m will produce the output only if -p is given as well. The default format
could be changed using log.diffMerges configuration parameter, which default value is separate.
--diff-merges=first-parent, --diff-merges=1
This option makes merge commits show the full diff with respect to the first parent only.
--diff-merges=separate
This makes merge commits show the full diff with respect to each of the parents.
Separate log entry and diff is generated for each parent.
--diff-merges=remerge, --diff-merges=r, --remerge-diff
With this option, two-parent merge commits are remerged to create a temporary
tree object -- potentially containing files with conflict markers and such.
A diff is then shown between that temporary tree and the actual merge commit.
The output emitted when this option is used is subject to change,
and so is its interaction with other options (unless explicitly documented).
--diff-merges=combined, --diff-merges=c, -c
With this option, diff output for a merge commit shows the differences from each of the parents
to the merge result simultaneously instead of showing pairwise diff between a parent and the result one at a time.
Furthermore, it lists only files which were modified from all parents. -c implies -p.
--diff-merges=dense-combined, --diff-merges=cc, --cc
With this option the output produced by --diff-merges=combined is further
compressed by omitting uninteresting hunks whose contents in the parents have
only two variants and the merge result picks one of them without modification.
--cc implies -p.
5条答案
按热度按时间mwg9r5ms1#
请使用以下选项之一:
你的问题中有一个根本性的错误:提交不是差异;提交是快照。这看起来似乎是一个没有区别的区别-对于一些提交,它是 *。但是对于合并提交,它不是 *。
当
git show
(或git log -p
)将一个提交 * 显示为 * 一个diff时,它是通过 * 将提交的快照与其他内容进行比较 * 来实现的。git diff
命令做同样的事情:它将一个提交与另一个提交进行比较。(或者它可以将一个提交与工作树进行比较,或者与索引的内容进行比较,或者与其他一些组合进行比较。)对于普通的提交,比较什么是显而易见的:比较 this commit的快照和 previous(即父)commit的快照。这就是
git show
所做的(还有git log -p
):它运行从父提交到该提交的git diff
。然而,合并提交并不是只有一个父提交,而是有 * 两个 * 父提交。1这就是为什么合并提交首先是“合并提交”:合并提交的定义是具有至少两个父提交。
1一个合并提交可以有三个或更多的父提交。这些被称为“章鱼合并”。它们没有做任何特别的事情,但是,主要是为了炫耀。:-)你可以在这里忽略它们。
当有两个父节点时,
git show
应该与哪一个进行比较?git log -p
在默认情况下根本不进行比较,您可以通过添加各种标志(见下文)使其显示某些内容。git show
在默认情况下选择做的事情更复杂。由于有两个父节点,git show
首先与“第一个父节点”进行比较,2然后与第二个父节点进行比较。然后-这部分非常关键-它组合两个差异,产生所谓的“组合差异”。在下一节中,让我注意一个棘手但非常有用的Git语法。如果你有一个像
c05f017
这样的提交ID,你可以在后面添加一个插入符号或“帽子”字符^
,来命名一个父提交。你可以选择添加另一个数字来选择 which parent。对于常规的(non-merge)commits只有一个,所以c05f017^
是 the parent。对于merge commits,c05f017^
和c05f017^1
都表示 the first parent,而c05f017^2
表示 the second parent。2我把这句话放在引号里是因为 first parent 这个概念在Git中特别重要,我们一会儿就会看到。换句话说,Git最关心的是哪个父节点是 first,而其余的只是“其余的”。
组合差异
文档中描述了组合的diff格式,但这里首先描述了一个关键位,以便使其特别模糊:3
请注意,combined diff 仅列出从所有父代修改的文件。
也就是说,假设 M 是一个合并提交,并且diff M^1 vs M 表示文件
mainline.txt
和common.txt
都被更改。进一步假设diff M^2 和 M 表示文件sidebranch.txt
和common.txt
都被更改。组合的diff将显示 *onlycommon.txt
*,跳过mainline.txt
和sidebranch.txt
,因为这两个文件只修改了 * 一个 * 父文件(每个)。(即使这样,Git也可能只显示common.txt
的一些差异。)3我花了很长时间才在文档中找到这一点,因为我一直在看其他部分。
区分
-m
选项-m 在这里可能代表 merge-告诉Git实际上“拆分”合并。也就是说,不要试图将每个父节点的差异组合成一个大的组合差异,而只是显示 each 父节点的差异,一次一个差异。有时候这是你想要的,但如果不是你想要的,你可以运行你自己的
git diff
来比较两个父类中的一个(或者见下文)。需要与哪个父节点进行diff比较?
通常,正确答案是“第一个父母”。
“第一个父分支”的关键在于,当Git进行合并提交时,它总是把你当时所在的分支记录为第一个父分支,而另一个分支则成为第二个父分支。
也就是说,如果你在
develop
上合并topic
:Git将在当前分支
develop
上创建一个新的提交-一个 merge commit,有两个父提交。合并提交的 * 第一个 * 父提交将是刚才develop
的提交。* 第二个 * 父提交将是(仍然)topic
的提交。由于你通常关心合并带来的是什么,与第一个父节点进行比较会给你带来什么。所以通常这就是你想要的。出于这个原因,
git show
允许你运行git show --first-parent
。这会“分割”提交,然后git show
只与第一个父节点进行比较。(这与git show -m
有点不同,它会分割提交两次:第一分割与第一父比较,第二分割与第二父比较)。类似地,你可以运行
git log -p --first-parent
在这里,--first-parent
标志有一个更重要的作用:log操作根本不查看分支的提交,只查看主行(第一父行)上的提交。注意,如果你的Git版本早于2.31,你仍然需要-m
标志(当使用git log
时,即;git show
默认为--cc
,因此不需要-m
,所有这些都在Git 2.31中进行了清理。1tuwyuhd2#
下面是一个简单的命令:
git show HEAD -m
考虑到它反映了其他常用的命令,也许它稍微更容易记住。
它显示合并后对合并分支所做的所有更改。
9ceoxa923#
参见
git show --diff-merges
,其中--diff-merges
是由Git 2.31 (Q1 2021)引入的。作为mentioned here,这些解决方案涉及显示组合的差异,如:
但是:当合并涉及重命名时,“
diff --cc
”的输出没有显示原始路径。Git 2.22(Q1 2019)中的一个新选项将原始树中的路径添加到输出中。
log
,diff-tree
:添加--combined-all-paths
选项合并的组合差异格式将只列出一个文件名,即使重命名或复制检测处于活动状态。
例如,对于原始格式,可能会看到:
这不会让我们知道
bar.sh
在第一个父节点中的原始名称,也不会让我们知道phooey.c
在任何一个父节点中的原始名称。相比之下,对于非合并提交,原始格式确实提供原始文件名(以及 Boot 的重命名得分)。
为了提供合并提交的原始文件名,添加一个
--combined-all-paths
选项(必须与-c
或--cc
一起使用,并且可能只在重命名或复制检测活动时有用),以便我们可以在涉及重命名时打印制表符分隔的文件名。这将上述输出转换为:
此外,在补丁格式中,这改变了from/to头,因此我们为每个父节点都得到一个“from”头,而不是只有一个“from”头。
例如,与其拥有
我们会看到
pn9klfpd4#
git show -c c0f501
将显示提交c0f501
到其双亲的组合差异,如git diff
在合并期间打印的。这给出了比
git show -m
更好的概述。但是,它只显示相对于双亲更改的文件中的更改(或至少两个用于octopus合并的父节点)。例如,当文件
f1
和f2
在第一个父节点上被改变,而f2
和f3
在第二个父节点上被改变时,这个命令只会显示f2
中的更改。f1
和f3
中的更改 * 不会 * 显示。因此,为了获得完整的概述,在使用git show -c
之前或之后使用git show -m
仍然是有意义的。以下是一个octopus合并的
git show -c
输出示例,其中包含两个文件中的更改,其中只有一个文件针对多个父文件进行了更改:相比之下,
git show -m
给出了以下冗长但完整的输出:gab6jxml5#
现代git有精心设计的diff选项: