到目前为止,我有一个历史悠久的 git repo。我试图对早期提交进行一些更改,并发现了奇怪的冲突。
我发现如果我做一个 git rebase COMMIT^ 并选择早期的一个,但是在列表上我什么都没碰,比如选择所有提交,它仍然会通过动作,重播所有提交,并且无法解释对我来说,有些失败。
这怎么可能?如果由于选择了所有提交而没有更改历史记录,那么它怎么会失败?
到目前为止,我有一个历史悠久的 git repo。我试图对早期提交进行一些更改,并发现了奇怪的冲突。
我发现如果我做一个 git rebase COMMIT^ 并选择早期的一个,但是在列表上我什么都没碰,比如选择所有提交,它仍然会通过动作,重播所有提交,并且无法解释对我来说,有些失败。
这怎么可能?如果由于选择了所有提交而没有更改历史记录,那么它怎么会失败?
rebase 通过“回放”每个 diff 中的更改来工作,进行新的提交(保持旧的完整,但隐藏,并最终到期)。“回放”提交的方法可以更直接地作为git cherry-pick
,所以我将首先描述这一点。
挑选樱桃涉及提取提交中所做的更改。然后,通过使用 diff 中包含的上下文,可以将生成的 diff 应用于(“修补”)一些其他(不同的)提交。但是,由于提交不会存储为更改——<a href="https://stackoverflow.com/a/8198276/1256452">每次提交都是源的完整“快照”——樱桃选择必须计算提交提供的更改。它通过将提交与其父提交进行比较来做到这一点。
这适用于线性历史,但在合并时效果不佳。特别是,根据定义,合并提交至少有两个父级(与两个以上的父级合并是不常见的,但 git 允许它们)。鉴于与两个父母的提交,并且没有明显的方法来选择在进行差异时要考虑哪个git cherry-pick
父母,只是抱怨而停止。它使您可以-m
选择在挑选合并提交时提供您关心的父级。
rebase 命令采用了不同的方法:默认情况下,它完全消除了合并,希望它们不是必需的。如果合并很重要(就像他们在这里所做的那样),这将导致挑选失败。
rebase 命令确实有一个-p
(aka --preserve-merges
) 选项。在这种情况下,它会尝试保持合并。在这种特殊情况下,您将提交序列重播到原始基本提交上,保留合并的 rebase 应该可以工作。
有关更多详细信息,请参阅文档。