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



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

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

这也不是一次性的。如果我这样做git rebase --skip之后还会发生几次冲突。

我实际上只是想理解为什么当没有任何变化时会有冲突。工作树干净,与远程保持同步。

编辑:发生的冲突出现在我几天前合并其他分支时修复的冲突。但只是,它们已经修复了。

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

好的,所以我们至少有:

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

其中branch标识提交E,您将AE复制到新的和改进的提交。 制作完五个副本后,您将拥有:

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 复制的十二个提交中,其他七个来自哪里?

上图必然是错误的

我们上面绘制的图表有五个提交要复制,有五个提交"之后"(不可到达)提交*。 提交*是从提交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,但AE中的任何一个都可能是合并,也可能有多个合并。

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

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 rebase -i传递的选项git rev-list得出的任何结果)。

请注意,变基的副作用是丢弃合并,用尝试线性化新提交来替换它们。 正是这种线性化和丢弃合并导致了您看到的合并冲突。

怎么办

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

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

...--o--o

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

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

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

您也可以使用后跟git filter-branchgit replace。 这甚至更加棘手,但在某些方面,比将交互式变基与-p相结合的危险性要小。

最后,虽然这是重复,但请考虑根本不这样做。 故意很难 - 好吧,不可能,第一次近似 - 更改现有提交中的内容。 你应该有一个很好的理由来重新复制提交。

最新更新