如果没有改变,为什么交互式git rebase会有冲突?

时间:2018-03-02 22:40:39

标签: git

这是我的情景。我需要更改一个被推送到远程的旧提交消息。我可以强行推动,因为我现在是唯一一个在分公司工作的人。

所以我按常规git rebase -i HEAD~5选择我要用r更改的提交,保存并继续。 Git做了它的改变,但当它到达(5/12)它停止因为它在几个文件中发现冲突,让我挠头并运行众所周知的git rebase --abort

它不仅仅是一次性的。如果我git rebase --skip之后还有几个冲突。

我实际上只是想了解为什么在没有任何改变时会发生冲突。工作树清理并与遥控器保持同步。

编辑:发生的冲突似乎是我几天前在其他分支合并时修复的。但就是这样,他们已经修好了。

1 个答案:

答案 0 :(得分:3)

  

所以我做了通常的git rebase -i HEAD~5 ......

好的,所以我们至少有:

...--o--*--A--B--C--D--E   <-- branch (HEAD)

其中branch标识提交E,并且您要将A - 通过 - E复制到新的和改进的提交中。制作完五份后,您将获得:

          A'-B'-C'-D'-E'  <-- branch (HEAD)
         /
...--o--*--A--B--C--D--E   [abandoned originals]

我们可以重新绘制为:

...--o--*--A'-B'-C'-D'-E'  <-- branch (HEAD)
         \
          A--B--C--D--E   [abandoned originals]

(这可能更舒服,但实际上是相同的图纸)。标记为prime-tick-marks '的提交是闪亮的新副本,它们以某种方式比原始文件更好(例如,更改其提交消息,或者 - 以后提交 - 使用闪亮的新父级的ID而不是沉闷的老父母。)

  

...但是当[Git]到达(5/12)......

哇,其他七个提交复制的地方来自哪里?

说真的,想一想这个问题:你要求Git复制的十二个提交中的其他七个来自哪里?

以上图表必然是错误的

我们上面绘制的图表,有五个提交要复制,有五个提交&#34;&#34;&#34; (不可到达)提交*。提交*是提交,它是从提交E返回的五个第一父步骤,即HEAD~5这一部分必然是正确的:提交*真的 从提交E返回五个第一父步骤,作为HEAD~5 意味着&#34;从HEAD&#34;向后遍历五个第一父链接并且HEAD标识了提交E(这就是为什么我们在此处将其称为提交E。)

因此图表必须看起来不同。一种合理可能的可能性是:

...o------o--*--A--B--C--D--E   <-- branch (HEAD)
    \                      /
     F--G--H--I--J--K--L--M

现在有 13 提交可以从名称branch(附加HEAD的分支名称)到达,即可以从提交*到达。其中一个是合并 - 我在这里选择了E,但AE中的任何一个都可能是合并,或者可能有多个合并。

您的git rebase将(尝试)将所有非合并提交复制到闪亮的新提交中,在提交*后放置所有 12

               F'-G'-H'-I'-J'-K'-L'-M'-A'-B'-C'-D'   <-- branch (HEAD)
              /
...o------o--*--A--B--C--D--E   [abandoned]
    \                      /
     F--G--H--I--J--K--L--M

或:

               A'-B'-C'-D'-F'-G'-H'-I'-J'-K'-L'-M'   <-- branch (HEAD)
              /
...o------o--*--A--B--C--D--E   [abandoned]
    \                      /
     F--G--H--I--J--K--L--M

(实际的顺序有点难以预测 - 考虑到git rev-list通过的选项,它来自git rebase -i的任何内容。

请注意,rebase的副作用是 discard 合并,将其替换为尝试线性化新提交。这种线性化和合并丢弃会导致您看到的合并冲突。

该怎么办

这取决于。首先要做的是发现图形的真实形状。我上面提到的只是一个猜测;可能还有其他形状。

假设实际形状看起来更像这样:

     ...--o--o
              \
...--o--o--o---o--X--o   <-- branch (HEAD)

并且我标记为X的提交是具有您要修复的提交消息拼写错误的提交。 此提交后面没有任何合并,因此您可以更轻松地修复它:只需选择之前的提交,在这种情况下为HEAD~3,作为{{1的基础}}

如果您想要修复其邮件的提交更早,请考虑使用git rebase -i,这将重建合并。您可能必须解决合并冲突。注意:将git rebase -i -p-i合并是很棘手的。考虑不要这样做。

您还可以使用-p,然后使用git replace。这更加棘手,但在某些方面,与将交互式rebase与git filter-branch相结合的危险性要小。

最后,虽然这是重复,但考虑不要这样做。它故意很难,不可能,以一个近似的方式 - 改变现有提交中的东西。你应该有很好的理由重新提交这些提交。