假定以下提交结构:
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
答案 0 :(得分:3)
在每种情况下,问题似乎都是由文件最后一行缺少换行符引起的,而面对丢失的换行符,则可能是带有重新设置基准的错误。从技术上讲,缺少最后一个换行符的文本文件不是“有效的”,我怀疑这意味着该案例很少经过测试。
我在您的样本回购上复制了该行为-感谢您对其进行私有化! -然后使用相同的文件创建了一个不同的沙箱,但是在每个州的最后一行都有一个换行符。
使用文件最终换行符,合并和变基都会产生:
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}}和1
,因为它们在您的文件中丢失。
我认为考虑2
== 1
是重新定位的错误,但是根据输入,输出是合理的。
答案 1 :(得分:1)
实际上,merge
和rebase
不会以相同的方式移动事物。因此,假设您当前站在分支 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”。