`git rebase master` 如何将重新应用的提交检查为冲突?

How does `git rebase master` check a reapplying commit as a conflict?

假设我们有两个示例及其提交(line 1, line 2...foo 文件的内容,它是工作目录中唯一的文件):

示例 1:

line 1     line 1
line 2     line 22
line 3     line 3
  C0---------C1 [master]
   \
    C2 [test]
  line 1
  line 222
  line 3

示例 2:

line 1     line 1
line 2     line 22
line 3     line 3
  C0---------C1 [master]
   \
    C2--------C3 [test]
  line 1     line 1
  line 22    line 222
  line 3     line 3

我 运行 git checkout testgit rebase master 在每个例子上,我看到例子 1 有冲突,而例子 2 没有冲突。

在示例 1 中,当重新应用 C2 时,我猜想 Git 在 C2C1C0 上进行了 3 向合并,这检测到 C2 上的 "line 222"C1 上的 "line 22" 不同,并且与基础 (C0) 上的 "line 2" 不同,因此 Git检查是否存在冲突。

在示例2中,C2的补丁已经在master中,所以Git跳过它。但是当重新应用 C3 时,如果 Git 在 C3C1C0 上进行了 3 向合并,它检测到 "line 222"C3C1 上的 "line 22" 不同,与基础 (C0) 上的 "line 2" 不同,那么 Git 应该将其检查为冲突,但在真正的 Git 没有。

所以实际上,Git 变基如何将重新应用的提交检查为冲突?

每个提交都被(或好像被)git cherry-pick 复制。 cherry-pick 是一种合并,其合并基础是被选择的提交的父级,--ours 版本是 HEAD 提交,--theirs 版本是被选择的提交。所以,给定:

C0--C1   <-- master
 \
  C2--C3   <-- test

和:

git checkout test && git rebase master

Git会先把C2复制到C2',再把C3复制到C3'.

复制C2时,合并基数为C0C2的parent),--oursC1([=26=的tip) ]),而 --theirsC2(被复制)。复制完成后我们有这个:

       C2'  <-- HEAD
      /
C0--C1   <-- master
 \
  C2--C3   <-- test

接下来,Git 挑选 C3。因此,合并基础是 C2C3 的父级),--oursC2'--theirsC3

如果 base 与我们的差异 (git diff) 与 base 与他们的差异触及同一文件的 "the same lines",则存在合并冲突。 "Same" 在这种情况下包括触摸行之后的一行。因此,将 C2(基础)的内容与 C2'C3 中的每一个进行比较,以查看我们更改了哪些行(C2C2')和他们的(C2 对比 C3)。如果我们在生成 C2' 时将 "their" 更改为第 2 行,则从 C2C2' 的差异为空,因此通过获取文件可以轻松解决合并来自 C3.