我想查看两个合并提交之间的差异,只更改第一个合并提交的文件

问题描述

通常,我在 git 中有这种情况

enter image description here

  • 蓝色是master,并且有一个共同祖先提交和两个合并提交
  • 绿色是 feature-branch-1feat1
  • 红色是feat2

两个分支都由 git 自动合并,但我知道存在一些“冲突”更改,我担心它们是如何解决的,但是,显示任何两个提交的差异会导致许多不相关文件中的大量更改。

是否可以看到 feat1feat2merge commits间的差异,但仅限于出现在 feat1 中的受feat2

解决方法

你想列出你的合并提交修改的文件:

1 - 列出一次提交的更改文件:

git show <SHA> --name-only --pretty=format:

2 - 比较两个合并提交的文件列表并获得交集:

comm -12  <(git show SHA1--name-only --pretty=format: |sort -u) <(git show SHA2--name-only --pretty=format: |sort -u)

3 - 现在您有了文件列表,您可以在循环中比较所有文件,例如:

for r in `comm -12  <(git show SHA1--name-only --pretty=format: |sort -u) <(git show SHA2--name-only --pretty=format: |sort -u)`; do git difftool SHA1 SHA2 "$r"; done

当然,您必须通过合并提交替换 SHA1 和 SHA2。

,

两个分支都由 git 自动合并,但我知道有一些“冲突”的变化,我担心它们是如何解决的......

目前还没有很好的方式来展示这一点。 (新的“merge-ORT”功能是一种使能技术,它将允许“伟大的方式”,或者至少是一种简单的单行命令方式来做到这一点,但它还没有出现。)

在我看来,找出如何处理冲突的最佳方法是重新执行合并。当你这样做时,你会遇到冲突。您不必完成合并:只需解决冲突即可。您现在拥有所有冲突文件的列表,并且可以将合并快照中的内容与任何给定其他提交中的内容进行比较。

要重新执行合并,请检查合并提交的第一个父项,可能作为分离的 HEAD,可能在添加的工作树中,因为您可能会在之后将其丢弃。下面的命令假设您有一个地方可以执行此操作(主工作树之外的 <path>)以及您希望测试的合并提交的哈希 ID:

git worktree add --detach <path> <hash>^1
cd <path>                    # or pushd,if using bash,zsh,etc
git merge <hash>^2

结果是上次发生的同一组合并冲突,假设进行合并的人使用了同一组 git merge 选项。

您现在可以查看任何合并冲突,并将它们与合并结果中存储的内容进行比较。例如,如果文件 conflicted.ext 是相关文件:

git show <hash>:conflicted.ext > resolved.ext

现在您可以使用您喜欢的任何比较工具(您的编辑器、三路合并处理程序等)来比较冲突的文件和已解决的文件。如果您愿意,也可以使用 git checkout-index --stage=all conflicted.ext 轻松获取三个合并输入文件。

现在,关于你的最后一个问题:

是否可以看到 feat1 和 feat2 的合并提交之间的差异,但仅限于 feat1 中引入的受 feat2 影响的文件?

您可以让 git diff diff 任何特定文件,但它会误导思考文件。从提交的角度考虑,因为git diff本身会比较存储在某个提交中的快照。您必须首先命名这两个提交。1 因此,如果 M1master 上合并提交 #1 的哈希 ID,它会合并提交 P1(master 上的父项,可能是在图表左边缘以蓝色显示的合并基础提交2)和 P2(大概是最右边的绿色提交)。你必须从这三个提交中选择两个

在这种特殊情况下(其中 P1 大概是合并基础提交),我们可以找出哪些文件是“在 {{1} }”,只需将合并结果快照合并基础快照进行比较。任何状态为 feat1(新添加)的文件都必须来自 A。但是,如果我们在合并基础和最终合并之间的 feat1 上有任何提交,新添加的文件可能来自 master 上的其他提交。所以这个案例很简单:

master

为我们获取此类文件的列表。如果我们假设 this 合并进展顺利,我们现在可以检查 git diff --name-only --diff-filter=A <P1> <M1> 合并并特别注意这些文件。但如果我们只是重复 M2 合并,那可能同样容易,甚至可能更容易。


1有一种叫做combined diff的东西,合并提交的M2产生它,git show可以产生一。然而,组合差异故意遗漏了一些东西。我认为,组合 diff 的目的是帮助显示合并冲突,但组合 diff 用于选择要省略的内容的机制使这种意图变得非常平淡。特别是,如果有人通过仅选择某个文件的父版本来错误地解决了冲突,组合差异将完全忽略该文件,从而隐藏合并错误的事实.

2我认为在这种情况下他们是对的,但我多年来使用 Atlassian 软件的经验是他们的一些图表有点不可靠。 (这并不罕见:GitHub 也有同样的问题。图很难。)