git rebase意外的合并结果

时间:2019-04-04 10:41:48

标签: git git-rebase

假定以下提交结构:

A ---- B(HEAD)
 \ 
   C

这些修订本中的文件内容。

A:

1

B:

1
2

C:

0
1

我想将B合并到C。如果我通过git merge C进行合并,则会发生预期的冲突。但是,如果我执行git rebase C,则git会静默地执行它,而不会发生任何冲突,但是结果出乎意料:

0
12

有人可以向我解释为什么会发生吗?我什至可以依靠变基吗?文档说,在另一个提交的尖端重新设置提交会重新应用。那么提交到第二行的“ 2”不会导致任何冲突,也不会吃掉换行符吗? 您可以在此仓库https://gitlab.com/timofei.davydik/rebase_problem.git

上对其进行测试
git checkout test
git rebase master

2 个答案:

答案 0 :(得分:3)

在每种情况下,问题似乎都是由文件最后一行缺少换行符引起的,而面对丢失的换行符,则可能是带有重新设置基准的错误。从技术上讲,缺少最后一个换行符的文本文件不是“有效的”,我怀疑这意味着该案例很少经过测试。

我在您的样本回购上复制了该行为-感谢您对其进行私有化! -然后使用相同的文件创建了一个不同的沙箱,但是在每个州的最后一行都有一个换行符。

使用文件最终换行符,合并和变基都会产生:

0
1
2

如您所愿。

我认为git merge在您的示例中遇到了冲突,因为它无法将11\n识别为相同,而git rebase则看到了“插入0 1前面的行继续前进,因为即使在1中缺少换行符,它也会在第一行找到1

git rebase产生0\n12的事实表明,它从C取出了0\n1,然后从B取出了2,而{ {1}}和1,因为它们在您的文件中丢失。

我认为考虑2 == 1是重新定位的错误,但是根据输入,输出是合理的。

答案 1 :(得分:1)

实际上,mergerebase不会以相同的方式移动事物。因此,假设您当前站在分支 B

  • git merge C将分支C的最高状态带到当前分支B。例如,当您在master分支上工作并尝试汇总本地开发分支的结果时,这很有用。
  • git rebase C将完整的分支B移动到C的顶部(作为目标目标)。为此,git实际上将通过向后浏览您的分支来查找特定于B的所有提交,直到git找到两个分支都共有的第一个提交(此处为“ A”点)。然后它将重播分支B在C之上的每个提交,即:重新应用每个变更集

这首先意味着rebase操作不是合并操作。然后,B引入的变更集实际上是“在1之后添加2”。

@@ -1 +1,2 @@
1
+2

在“ A”处,您的文件仅包含“ 1”,因此最终将以“ 1”“ 2”结尾。 在“ C”处,您的文件包含“ 0”“ 1”,因此您将获得“ 0”“ 1”“ 2”。