我建议您编辑您的问题以包含您尝试重新设置 --onto 的确切命令。这应该是您完成您正在尝试的方式的方式,但您可能已经以这种方式运行命令以触发比实际需要更多的变基。
如果你的 rebase 命令重写了v1.0
和之间的所有内容v.2.0
,那么如果该历史记录包括通过非快进合并解决的冲突,这可能会导致很多不必要的痛苦。
为了清楚起见,我已将有关合并冲突和变基的解释移至此答案的底部。rebase --onto
但是,该部分只是推测,查看您尝试的示例会很有帮助。现在没有可用的,我会提供我认为你应该做的。话虽如此,让我们开始您的解决方案。
解决方案
变基--onto
我喜欢向后阅读 --onto 的论点以更好地理解。向后阅读,--onto <1> <2> <3>
读为 - 将任何提交在 上<3>
,未在 上<2>
,并将它们应用于<1>
. 提交不是“移动”的,而是“克隆”的,因此您的旧提交仍然在原处 - rebase --onto 只是创建它们的副本并在<1>
.
重要的是要知道,在执行 a 之后,rebase --onto
您最终可能会处于无头状态。如上所述应用新提交,但它们不会立即更改分支的状态。这在该过程中增加了一个额外的步骤,但也为您提供了额外的安全性,即知道变基不会破坏您的分支 - 您将有机会在将这些更改应用于您的分支之前查看更改的历史记录。
从这张图开始。
E<--G<--H v1.1
/
A<--B<--C<--D Master
\
F v2.1
根据您的描述,要获取 onlyG
并H
遵循F
,而不包括,那么您应该尝试以下命令。E
git rebase --onto F G^ v1.1
如果你的情况,我写了上面的假设尽可能少。
这将立即处理提交v1.1
中 存在G
的任何提交,并在之后应用它们F
。由于实际被重写的唯一提交是G
and H
,因此没有理由让您遇到与这两个提交更改的内容无关的任何冲突。
无头状态
如上所述,您最终可能会处于无头状态。这意味着您不再在您的分支中。您此时的图表实际上看起来像这样......
E<--G<--H v1.1
/
A<--B<--C<--D Master
\
F v2.1
\
G'<--H' (currently checkout out headless state)
如您所见,分支 v2.1 仍位于F
,但您已经创建了A<--B<--C<--F<--G'<--H'
. 这是您想要的,但它不在您的v2.1
分支中。因此,现在查看您的历史记录并确认它是您想要的。如果你愿意,甚至可以测试它。验证后,您只需签出 v2.1 并运行以下命令...
git checkout v2.1
git merge H'
这假设您在 v2.1 上没有新的提交,这些提交不在H'
. 为确保,您可能希望--ff-only
在合并上使用标志,以便它将拒绝合并而不是创建合并提交。
就像我上面所说的,这是一个需要注意的额外步骤,但因此您可以重置确保git rebase --onto
不会在您的实际分支上弄得一团糟。如果您发现 rebase 没有按预期工作 - 您可以简单地检查v2.1
并查看没有造成任何伤害。
结果
在您的快进合并完成后,您将拥有如下所示的历史记录...
E<--G<--H v1.1
/
A<--B<--C<--D Master
\
F<--G'<--H' v2.1
Cherry-picking vs Rebase --onto
不会详细介绍樱桃采摘,但我想明确以下..
git checkout v2.1
git cherry-pick G^..H
也完全等价...
git rebase --onto v2.1 G^ H
git checkout v2.1
git reset --hard <hash> <-- were hash is the commit the rebase kicks you into.
Cherry pick 的步骤更少,rebase 可以在不检查“base”的情况下完成,在这两种情况下都是v2.1
. 同样如前所述, rebase --onto 不会直接影响您的分支,如果出现问题,则更容易从中恢复。两者都“克隆”了他们带到基础上的提交,而原件保持不变。
问题
以上是关于如何实现您要求做的事情的一般解释。以下是我对您为什么遇到您所描述的问题的怀疑。
非快进冲突解决和变基
我的猜测是,在 v1.0 和 v2.0 之间,您有一些用于解决冲突的非快进合并。在非快进合并期间解决冲突时,该冲突的解决方案将存储在合并提交中,而不是存储在有问题的提交本身中。合并提交发生在合并点的历史后期,而不是冲突提交本身。
当您变基时,git 会单独执行每个提交并重新提交它 - 结果,您将重温由非快进合并引起的所有冲突,但该冲突的解决方案直到合并发生的历史后期才可用。使用非快进合并解决的冲突不利于您将来重新设置分支的能力,除非您愿意一一重新解决所有这些冲突。
你可能犯的错误
如果我对您的问题的猜测是正确的,那么您可能已经做了以下事情......
git rebase --onto v1.1 F v1.1
这个或这个的一些变体将导致获取所有F
未打开 的提交v1.1
并将它们附加到v1.1
. 如上所述,这将导致每次提交之间B
并被F
一一重新提交。如果其中存在通过非快进合并解决的冲突 - 那么您将通过这些提交重新体验这些冲突中的每一个作为 rebase 步骤。
合并而不是变基
您的问题标题表明您可能愿意简单地合并这些历史。如果您不关心线性历史,您可能只想将 v1.1 合并到F
. 这不应该导致任何奇怪的冲突,但它会严重混淆你的历史。