我建议您编辑问题,包括您尝试重新定位的确切命令。这应该是您实现所需内容的方式,但如果您以触发比实际必要更多的重新定位的方式运行命令,则可能会导致许多不必要的痛苦。
如果您的重新定位命令重写了v1.0
和v.2.0
之间的所有内容,那么如果该历史记录包括通过非快进合并解决的冲突,则可能会导致很多不必要的痛苦。
为了清晰起见,我已将有关合并冲突和重新定位的说明移至此答案的底部。但是,该部分仅是猜测,看到您尝试的rebase --onto
示例将很有帮助。现在没有可用的内容,我将提供我认为您应该执行的操作。有了这个前提,让我们开始解决方案。
解决方案
Rebase --onto
我喜欢倒着阅读--onto的参数以更好地理解。倒着读,--onto <1> <2> <3>
读作-获取在<3>
上的任何提交,不在<2>
上,并将其应用于<1>
。提交并没有“移动”,它们是“克隆”的,因此您的旧提交仍然在原地-重新定位--onto只是创建了它们的副本并将它们应用于<1>
之后。
重要的是要知道,在执行rebase --onto
之后,您可能会处于无头状态。新提交按上述方式应用,但它们不会立即更改您的分支状态。这增加了一个额外的步骤,但也为您提供了额外的安全保障,以确保重新定位不会破坏您的分支-您将有机会在将这些更改应用于您的分支之前审查已更改的历史记录。
从这张图开始。
E<
/
A<
\
F v2.1
为了让只有
G
和
H
跟随
F
,而
不包括E
,这是根据您的描述看起来的情况,那么您应该尝试以下命令。
git rebase --onto F G^ v1.1
假设你的情况我了解得很少,以下是我的翻译:
这将获取在v1.1
上存在但在紧随G
提交的提交中不存在的所有提交,并在F
之后应用它们。由于实际被重写的提交只有G
和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
,而不会弄乱您的实际分支。如果您发现重新基础不按预期工作 - 您可以简单地检出v2.1
并查看未造成任何伤害。
结果
完成快进合并后,您将拥有以下历史记录...
E<
/
A<
\
F<
挑拣(cherry-picking)与重置基础(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.
樱桃挑选具有较少的步骤,可以在不检出“基础”(在这两种情况下都是
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步骤中会重现每个冲突。
合并而不是rebasing:
您的问题标题表明您可能愿意简单地合并这些历史记录。如果您不关心线性历史记录,则可以将v1.1简单合并到
F
中。这不应该导致任何奇怪的冲突,但它将显著混淆您的历史记录。