假设以下提交结构:
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
看起来问题是由于每种情况下文件最后一行都缺少换行符引起的,并且可能是在遇到缺少的换行符时出现rebase错误。从技术上讲,文本文件在缺少最终换行符时不是“有效”,我怀疑这意味着很少测试该案例。
我重现你的样品回购的行为 - 感谢提供它! - 然后使用相同的文件创建一个不同的沙箱,但每个状态的最后一行都有换行符。
使用文件最终换行符,合并和rebase都会生成:
0
1
2
正如你所料。
我认为git merge
在你的例子中看到了冲突,因为它没有认识到1
和1\n
是相同的,而git rebase
看到“在0
之前插入1
”继续前进,因为它在第一行找到1
,即使新线缺少1
。
git rebase
产生0\n12
这一事实表明它从C中获取了0\n
和1
,然后从B中获得了2
,而1
和2
缺少了换行符,因为它们在你的文件中丢失了。
我会说这是一个错误,因为rebase考虑了1
== 1\n
,但是否则根据输入输出是合理的。
实际上,merge
和rebase
不会以同样的方式移动东西。所以,假设你现在站在分支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”。