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

问题描述 投票:0回答:1

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

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

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

我实际上只是想了解为什么在没有任何改变的情况下会发生冲突。工作树清洁和最新的远程。

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

git
1个回答
3
投票

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

好的,所以我们至少有:

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

其中branch识别提交E,你将把A-through-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]

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

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

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

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

The above graph is necessarily wrong

我们上面绘制的图表有五个提交要复制,有五个提交“后”(不可达 - 来自)提交*。提交*是从提交E返回的五个第一父级步骤的提交,即HEAD~5。这一部分必然是正确的:提交*确实是从提交E返回的五个第一父级步骤,因为HEAD~5意味着“从HEAD向后遍历五个第一父链接”,而HEAD识别提交E(这就是为什么我们称之为提交E)。

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

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

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

你的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的副作用是放弃合并,将其替换为尝试线性化新提交。正是这种线性化和合并丢弃导致了你看到的合并冲突。

What to do about it

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

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

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

我标记为X的提交是一个你想修复的提交消息拼写错误的提交。任何合并都不会跟随此提交,因此您可以更轻松地修复它:只需选择之前的提交,在本例中为HEAD~3,作为git rebase -i的基础。

如果您想要修复其消息的提交更早,请考虑使用git rebase -i -p,它将重建合并。您可能必须解决合并冲突。小心:将-i-p结合起来很棘手。考虑不要这样做。

您也可以使用git replace,然后使用git filter-branch。这更加棘手,但在某些方面,比将交互式rebase与-p结合起来要危险得多。

最后,虽然这是重复,但考虑不要这样做。对于现有提交中的事情,改变事物的意图是故意的,不可能的,不可能的。你应该有一个非常好的理由来重新提交这些提交。

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