如何查看/展示已完成的Git合并冲突解决方案,给定合并提交SHA1?

52
当您解决冲突并分期更改后,进行git diff操作时,它会显示两列'+'和'-',分别代表“我们”的更改和“他们”的更改。在存储库的git历史记录中给定合并提交,如何查看由其他人完成的此次解决方案?在其他情况下,我以前看过它(在gitk中),但我似乎无法确定我拥有的SHA1的解决方案。

然后执行git diff,它会显示两列加号和减号,一列是"ours",另一列是"theirs" ... 真的吗?你的git配置如何? - gcbenison
1
@gcbenison:只有在你处理合并冲突,在提交冲突解决之前才会出现这种情况。我认为这不需要任何特殊的配置。 - Pistos
3
在 Git 2.36 (Q2 2022) 中,git log --remerge-diff 命令将会展示你在合并冲突解决中所做的工作!请参见下面的回答 - VonC
3个回答

62
如果你知道引用(ref),那么git show <MERGE_COMMIT>将会显示出合并提交所做的解决方案(如果有的话)。
对于日志,使用git log -p -cgit log -p --cc。来自git log的手册页面。
   -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.

   --cc
       This flag implies the -c option and further compresses the patch output by 
       omitting uninteresting hunks whose contents in the parents have only two 
       variants and the merge result picks one of them without modification.

2
这有点儿奏效。我仍然看到了一堆变更,这些变更只是由其中一个合并头引入的,我不确定是否因为我连续有两个合并提交?我看到了所有无趣的冲突解决(这些都是由kdiff3解决的),以及有趣的那些。我注意到有趣的那些前面带有++,而不是+或-。 - chrisortman
3
如果分辨率与基础分辨率相同,则不显示分辨率差异。 - stevemao
4
实际上,如果分辨率与任何一方的更改相同,则不会显示任何差异。 - stevemao
它可以正常工作。可以参考这篇详细的博客。另外一件事,git show <COMMIT> --stat仍然会显示完整的更改文件。 - edvard chen

27

更近期的选择(2022年,九年后)是:

git log --remerge-diff

在 Git 2.36 (2022 年第二季度) 中, "git log --remerge-diff"(man) 显示机械合并结果和实际记录在合并提交中的结果之间的差异。

请参考以下提交记录:commit 0dec322, commit 0d83d82, commit 20323d1, commit 95433ee, commit 6054d1a, commit a28d094, commit 24dbdab, commit 35f6967, commit 7b90ab4, commit db757e8 (2022年2月2日) 由Elijah Newren (newren)提交。
请参考以下提交记录:commit 5046831 (2021年12月21日) 由Junio C Hamano (gitster)提交。
(合并自Junio C Hamano -- gitster --commit 90b7153,2022年2月16日)

show, log: 提供 --remerge-diff 功能

署名:Elijah Newren

当使用此选项时,我们会重新合并所有 (两个父节点的) 合并提交,并将实际的合并提交与自动创建的版本进行差异比较,以展示用户如何:

  • 删除冲突标记,
  • 解决不同的冲突版本,以及
  • 可能在解决语义合并问题时添加新的更改**(或者可能只是为了隐藏其他随机更改)。

此功能通过创建一个临时对象目录并将其标记为主要对象存储来实现。
这样一来,在自动合并过程中创建的任何 blob 或 tree 都可以通过仅删除临时对象目录中的所有对象来轻松移除。

此实现存在一些次优点:

  • log --remerge-diff 变得很慢,因为在运行时,临时对象目录可能会填满许多松散的对象。
  • 日志输出可能会混淆 "warning: cannot merge binary files" 消息的位置,因为 ll-merge.c 在运行时无条件将这些消息写入 stderr 而不允许调用方管理它们。
  • 重要的冲突和警告消息被简单地丢弃;因此,对于像修改/删除、重命名/重命名或文件/目录这样不能用内容冲突标记表示的冲突,--remerge-diff 的用户可能无法知道已经存在一个已解决的冲突(并且这可能激发了合并提交中的其他更改)。
  • 在解决上述问题时,需要注意有些不重要的冲突和警告消息可能开始被包含。
    相反,我们应该确保这些消息仍然被丢弃。
    后续的提交将解决这些问题。

diff-options 现在在其man page中包括:

--diff-merges=(off|none|on|first-parent|1|separate|m|combined|c|dense-combined|cc|remerge|r)

diff-options现在在其手册页面中包括以下内容:

--diff-merges=remerge:

--diff-merges=r:

--remerge-diff:

使用此选项,两个父合并提交将重新合并以创建一个临时树对象 - 可能包含有冲突标记等文件。

然后显示该临时树与实际合并提交之间的差异。

当使用此选项时发出的输出可能会更改,它与其他选项的交互也可能会更改(除非有明确的文档)。


请注意,上面的提交之一在Git 2.36(2022年第二季度)中有所撤销:

请参见提交624a935(由Elijah Newren (newren)于2022年3月2日提交)。
(由Junio C Hamano -- gitster --合并于提交8b44e05, 2022年3月13日)

merge-ort:默认情况下排除内部合并的消息

签署者:Elijah Newren

当设置GIT_MERGE_VERBOSITY为5时,merge-recursive仅会报告来自内部合并的信息。现在对于merge-ort也做同样的处理。

请注意,基于以下两个事实,0d83d82("merge-ort: 标记内部合并的冲突/警告信息可以省略",2022-02-02,Git v2.36.0 -- merge列在batch #4中)有所回退:

  • 这个提交基本上也删除了显示来自内部合并的消息,至少默认情况下。唯一的区别是用户可以通过增加详细程度来要求它们返回。
  • 4a3d86e("merge-ort: 使递归合并的信息更清晰",2022-02-17,Git v2.36.0 -- merge列在batch #8中)以来,来自内部合并的消息已经被特别注释。
    能够将其与外部合并评论区分开,使其包含起来不那么麻烦,并且更易于人类解析。

感谢你的回答。你能帮我实践一下吗?假设我有一个合并提交 SHA 111,我想要:在完成合并之前查看冲突的详细情况(例如文件列表或三方差异比较如 111^1 合并基础 111^2),然后-准确地了解他是如何解决这个冲突的(你的回答)。所以基本上我想要研究他的行动:我想要将他最初的冲突与他解决冲突的方法进行比较。这在 Git 中是否可能?谢谢 - Max
1
@Max 从git log --remerge-diff 111^!开始:这是一个限制在111上的日志,它应该显示出机械合并结果与实际记录在合并提交(111)中的结果之间的差异。 - VonC

0
小问题:您可以使用diff3或kdiff3来查看反向合并,特别是如果它是一个(git风格的)“恶意”合并,其中引入了次要更改以解决冲突。(注意不要让自己的头爆炸,试图看到它如何“撤消”更改;-))
显然,“基础”提交将是合并提交。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接