tl;博士
在您的情况下,使用git rebase --onto 在A 之上重新设置B 的正确语法是:
git checkout B
git rebase --onto A B^
或在A之上重新设置B,从B的父提交开始引用B^或B~1。
如果您对git rebase <branch> 和git rebase --onto <branch> 之间的区别感兴趣,请继续阅读。
快速:git rebase
git rebase <branch> 将在<branch> 的可访问的最新提交之上重新设置您当前已签出的分支,由HEAD 引用,但不是 来自HEAD.
这是最常见的变基案例,可以说是需要较少预先计划的案例。
Before After
A---B---C---F---G (branch) A---B---C---F---G (branch)
\ \
D---E (HEAD) D---E (HEAD)
在此示例中,F 和 G 是可从 branch 访问但不能从 HEAD 访问的提交。说git rebase branch 将采用D,这是分支点之后的第一个提交,并且重新设置它(即更改其父级)在最新的可到达提交之上来自branch,但不是来自HEAD,即G。
精确:带有 2 个参数的 git rebase --onto
git rebase --onto 允许您从特定提交开始。它使您可以精确控制要重新定位的内容和位置。这适用于需要精确的场景。
例如,假设我们需要从E 开始精确地在F 之上重新定义HEAD。我们只想将F 引入我们的工作分支,同时我们不想保留D,因为它包含一些不兼容的更改。
Before After
A---B---C---F---G (branch) A---B---C---F---G (branch)
\ \
D---E---H---I (HEAD) E---H---I (HEAD)
在这种情况下,我们会说git rebase --onto F D。这意味着:
在F 之上重新设置从HEAD 的父级为D 可访问的提交。
换句话说,将E 的父级从D 更改为F。那么git rebase --onto 的语法就是git rebase --onto <newparent> <oldparent>。
另一个派上用场的场景是,当您想快速从当前分支中删除一些提交而无需执行交互式变基:
Before After
A---B---C---E---F (HEAD) A---B---F (HEAD)
在此示例中,为了从序列中删除 C 和 E,您可以说 git rebase --onto B E,或者在 B 之上重新设置 HEAD,其中旧父级是 E。
外科医生:带有 3 个参数的 git rebase --onto
git rebase --onto 在精度方面可以更进一步。事实上,它允许您将任意范围的提交重新设置在另一个之上。
这是一个例子:
Before After
A---B---C---F---G (branch) A---B---C---F---G (branch)
\ \
D---E---H---I (HEAD) E---H (HEAD)
在这种情况下,我们希望在F 之上重新调整确切范围E---H,忽略HEAD 当前指向的位置。我们可以通过说git rebase --onto F D H 来做到这一点,这意味着:
在F 的基础上,将父级为D 的提交范围重新设置为H。
带有提交范围的git rebase --onto 的语法然后变成git rebase --onto <newparent> <oldparent> <until>。这里的技巧是记住<until> 引用的提交在范围内包含,并且在rebase 完成后将成为新的HEAD。