Git rebase意外合并结果

问题描述 投票:3回答:2

假设以下提交结构:

A ---- B(HEAD)
 \ 
   C

这些修订中的文件内容。

A:

1

B:

1
2

C:

0
1

我想将B合并到C.如果我通过git merge C这样做,我会遇到预期的冲突。但是,如果我做一个git rebase C然后git默默地做它没有任何冲突,但结果是意外的:

0
12

任何人都可以向我解释为什么会发生这种情况?我还能依靠rebase吗?文档说,rebase在另一次提交的提示上重新提交提交。那么为什么在第二行添加“2”不会导致任何冲突并“吃掉”换行符?你可以在这个repo https://gitlab.com/timofei.davydik/rebase_problem.git上测试它

git checkout test
git rebase master
git git-rebase
2个回答
3
投票

看起来问题是由于每种情况下文件最后一行都缺少换行符引起的,并且可能是在遇到缺少的换行符时出现rebase错误。从技术上讲,文本文件在缺少最终换行符时不是“有效”,我怀疑这意味着很少测试该案例。

我重现你的样品回购的行为 - 感谢提供它! - 然后使用相同的文件创建一个不同的沙箱,但每个状态的最后一行都有换行符。

使用文件最终换行符,合并和rebase都会生成:

0
1
2

正如你所料。

我认为git merge在你的例子中看到了冲突,因为它没有认识到11\n是相同的,而git rebase看到“在0之前插入1”继续前进,因为它在第一行找到1,即使新线缺少1

git rebase产生0\n12这一事实表明它从C中获取了0\n1,然后从B中获得了2,而12缺少了换行符,因为它们在你的文件中丢失了。

我会说这是一个错误,因为rebase考虑了1 == 1\n,但是否则根据输入输出是合理的。


1
投票

实际上,mergerebase不会以同样的方式移动东西。所以,假设你现在站在分支B上:

  • git merge C会将分支C的顶级状态带到当前的分支B.例如,当您在主分支上工作并尝试聚合本地开发分支的结果时,这很有用。
  • git rebase C将在C顶部移动您的完整分支B(作为目标目标)。为此,git实际上会通过向后浏览你的分支来找到所有特定于B的提交,直到他发现第一个提交对你的两个分支都是通用的(这里是“A”点)。然后,它将在C顶部重放分支B的每个提交,即:重新应用每个变更集。

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

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

在“A”,您的文件只包含“1”,因此您最终会得到“1”“2”。在“C”,您的文件包含“0”“1”,因此您将获得“0”“1”“2”。

© www.soinside.com 2019 - 2024. All rights reserved.