假设我有以下情景:
o (master)
/ o--o (WIP1)
/ /
o--o--o--o--o--o (WIP2)
(X) \
o--o (WIP3)
有没有一个Git命令可以创建一个新分支,使它包含分支X后的子树?我想执行一个“大型变基”,我希望将三个WIP分支变基到主分支上。
我知道我可以使用一些Bash脚本来完成这个操作,但我想知道如何使用Git命令来做到这一点。
假设我有以下情景:
o (master)
/ o--o (WIP1)
/ /
o--o--o--o--o--o (WIP2)
(X) \
o--o (WIP3)
有没有一个Git命令可以创建一个新分支,使它包含分支X后的子树?我想执行一个“大型变基”,我希望将三个WIP分支变基到主分支上。
我知道我可以使用一些Bash脚本来完成这个操作,但我想知道如何使用Git命令来做到这一点。
没有针对此操作的单一git命令。您需要进行一些手动工作。在您的情况下:
o (master)
/ o--o (WIP1)
/ /
X--o--o--B--o--o (WIP2)
\
o--o (WIP3)
你首先需要将WIP1变基到主分支(master):
git rebase --onto master X WIP1
这将导致如下结果:
o--o (WIP1)
(master) /
o--o--o--B’
/
/
X--o--o--B--o--o (WIP2)
\
o--o (WIP3)
如果你现在运行git rebase --onto master X WIP2
,你会得到这个结构:
o--o (WIP1)
(master) /
o--o--o--B’
/ \
/ o--o--B’’--o--o (WIP2)
/
X--o--o--B--o--o (WIP3)
这可能不是您想要的,所以现在您应该在B’
上变基WIP2和WIP3:
git rebase --onto B’ B WIP2
git rebase --onto B’ B WIP3
这将导致以下情况:
o--o (WIP1)
(master) /
o--X--o--o--B’--o--o (WIP2)
\
o--o (WIP3)
--preserve-merges
选项的 rebase 命令。合并所有分支将 暴露 1 个终点,该终点将用作 rebase --onto
的最终输入参数。起点通常很明显,即要移动的子树的原点。-Xours
选项自动解决它们。合并结果不重要,因为这些 人工 合并节点将在 rebase 后被丢弃。$ git checkout -b pack WIP1 # create new branch at 'WIP1'
$ git merge -s recursive -Xours WIP2 # merges WIP2 into pack (node p2)
$ git merge -s recursive -Xours WIP3 # merges WIP3 into pack
o (master)
/
/ (WIP1) (p2)
/ o-----o-----o----o (pack)
/ / / /
o--o--o--o-----o-----o / (WIP2)
(X) \ /
o------------o (WIP3)
$ git rebase --preserve-merges --onto master X pack
(WIP1') (p2')
o-----o-----o----o (pack')
(master) / / /
o----o----o--o--o-----o-----o / (WIP2')
(X) \ /
o------------o (WIP3')
现在是重新排列引用的时候了。我不知道为什么,在某些情况下,引用会被移动,而在其他情况下不会。对于每个引用WIP1、WIP2、WIP3或您需要的任何引用类型,请键入:
$ git checkout WIP1
$ git reset --hard <WIP1' hash>
$ git branch -D pack
$ git branch -D p2 # if there is any
(WIP1')
o-----o
(master) /
o----o----o--o--o-----o-----o (WIP2')
(X) \
o------------o (WIP3')
git rebase -i --rebase-merges
来简化此过程,以便您可以省略过程末尾的虚拟合并提交。在这里讨论:https://dev59.com/t2Uq5IYBdhLWcg3wbv5Z#69396585 - Waleed Khan使用git-branchless
工具套件,您可以直接重新定位子树:
$ git move -b WIP1 -d master
声明:本人为作者。
如果您想坚持使用基本的Git,您可以使用此答案中的方法,但要使用新的--rebase-merges
选项。创建一个虚拟合并提交:
$ git checkout WIP1
$ git merge WIP2 WIP3
...add all conflicts and resolve...
然后进行交互式变基。生成的变基计划将是您想要的,除了应该删除最后一个 merge
命令:
$ git rebase -i master --rebase-merges
...example editor contents below...
label onto
# Branch WIP1
reset abc123
pick abc456
pick abc789
label abcdef
reset onto
pick bcd123
pick bcd456
pick bcd789
## REMOVE THIS LINE:
# merge -C abcdef
o (master)
/ o--o (WIP1)
/ /
o--p--p--o--o--o (WIP2)
(X) (Y)
\
o--o (WIP3)
这应该是一个 rebase --onto
(你可以在 "如何将某些提交移动到git中的另一个分支?" 中看到一个例子):
git rebase --onto master X WIP1
git rebase --onto master X WIP2
git rebase --onto master X WIP3
p'--p'--o--o (WIP2)
/
o-----o-----p--p--o--o--o (WIP1)
(X) (master) (Y')
\
p''--p''--o--o (WIP3)
第一次变基没问题,但你需要获取Y SHA,然后:
git rebase --onto Y' Y WIP2
git rebase --onto Y' Y WIP3
X
后的前两个提交只存在于 WIP1
中?而 WIP2,3
直接从 master
开始? - VonC