这不是真正的答案(应该是评论),但它需要格式化并且不适合评论空间。相反,这是关于如何找到答案的说明,或者至少提出将导致答案的正确输入。
当你运行时:
git checkout master
git merge report
Git 首先找到一个 merge base 提交。很少——可能不是这里的情况——Git 发现多个合并基础提交,但我们会确保不是这种情况。
假设这个合并会出错,但是——重要的是——还没有完成。如果它已经完成,我们需要一个技巧,或者一个尚未完成的单独存储库:任何一个都足够了。诀窍是创建一个 new 分支,而不是命名为 master,它指向 master 在合并之前会指向的提交:
git checkout -b test-the-merge <hash-ID>
(我们可以稍后丢弃这个分支。或者,我们甚至可以根本不创建它,使用另一种技巧,但为简单起见,使用测试分支更容易。)
现在我们处于尚未完成合并的状态,我们首先运行:
git merge-base --all HEAD report
理想情况下,这会产生 one 哈希 ID。如果它产生多个哈希ID,我们会遇到有多个合并基础的罕见情况,我们需要一个我将省略的过程,因为它很长而且很无聊。 :-)
现在我们知道了作为合并基础的一个哈希 ID,下面是我们如何看到 Git 将看到什么,当 Git 进行合并时:
git diff --find-renames <hash> HEAD # what does Git think *we* changed?
git diff --find-renames <hash> report # what does Git think *they* changed?
您可能希望将这两个git diffs 发送到文件中,以便您可以在闲暇时和/或同时阅读它们。如果有很多正确合并的差异并且您只想专注于未正确合并的特定文件,您还可以将输出限制为特定文件。
请注意,git diff 发现的不一定是某些人所做的更改。 git diff 发现的是一组最小的指令,产生相同的效果。这通常足够好。例如,假设在左侧提交(合并基础,由哈希 ID 指定)和右侧提交之间,有人删除了 second 行,第一个单词 the,冗余段落:
Paris in
the
the
spring
而 Git 选择生成指令:删除第二个 the(第三行)。
这有关系吗?可能不会——但有时会。如果左右两边分别读:
some vaguely C like code {
with redundant stuff
}
more vaguely C like code {
with redundant stuff
}
和:
some vaguely C like code {
with redundant stuff
}
still vaguely C like code {
with redundant stuff
}
more vaguely C like code {
with redundant stuff
}
并且 Git 错误地在右大括号上同步并产生语法上无效的差异?好吧,即使通常仍然有效,但有时会产生不适当的冲突。在极少数情况下(尽管确实会发生,但很难说明),您可能会错过一个应该发生的冲突,因为 Git 提供了最小的编辑这在语法上是正确的,但在语义上是错误的。
无论如何,在生成两个差异列表之后,Git 现在所做的就是提出合并的源文件集。为此,Git 从所有文件的 merge base 版本开始。那么:
尽其所能将所有内容组合在一起,Git 现在:
- 因合并冲突而停止,或
- 因为你告诉它停止(例如
--no-commit),或者
- 进行合并提交,因为一切似乎都很顺利。
如果 Git 进行了合并提交——或者如果它停止并允许你提交并且你确实成功了——合并提交将你当前分支的旧提示提交作为其第一个父项——新提示提交是合并提交本身——并且合并提交将另一个分支的提示提交作为其第二个父级。也就是说,在master 或test-the-merge(无论我们在哪个分支)上合并之后,我们有:
git rev-parse <branch>^1 => hash ID of the previous branch tip
git rev-parse <branch>^2 => same hash ID as git rev-parse report
您可以查看两个输入,来自三个提交的两个差异 - 合并基础,HEAD 和他们的 /tip-of-report - 看看 Git 看到了什么,这将解释为什么 Git进行了它所做的合并。
无论如何,这就是 git merge 所做的事情: 它找到一个合并基础,创建两个差异,然后合并差异并将合并后的差异应用于合并基础以提出合并结果。 (这当然忽略了所有特殊情况,例如由于各种原因未实际合并:-s ours,或快进,或不相关的历史,或合并冲突等。)差异本质上是面向行的,不能重构某人真正所做的事情:他们只产生一组指令,这些指令会产生相同的最终文本。结合这些指令往往适用于大多数编程语言,但绝对不是完美的。
如果该过程适用于您的文件,您可以信任它。如果该过程不处理您的文件,则您无法信任它,并且您必须仔细检查 - 并在需要时更正 - 每次合并。