请考虑以下情况:
所以,如果我最初:
(1) (2)
x--x--x--x--x--x--x master
\ \
y--y--Y--y--y dev
(2)(3) (4)
我想得到:
(1) (2)
x--x--x--x--x--x--x master
\ \
y--y--------Y'--y'--y' dev
(2) (5) (5)
如果我只做git rebase master
,它将从2和4重新提交提交并从3删除合并。这不是我想要的。
还可以选择在3合并提交之前执行git merge master
,然后执行git rebase -i -p
,并在合并之后从3移动最后一次合并,然后将修复/压缩到3中的合并中。 strong>更新:它不那么容易。 Git拒绝压制两个合并。这个问题:git rebase interactive: squash merge commits together。
答案 0 :(得分:2)
你从:
开始 (1)
x--x--x--x--x--x--x master
\ \
y--y--Y--y--y dev
(2)(3) (4)
git branch dev1 Y^
git rebase --onto master Y^ dev
Y^
引用合并提交的第一个父级Y
:此处为“y
”,而不是“x
”。
请参阅“Ancestry References”:
第一个父项是您合并时所在的分支,第二个是您合并的分支上的提交。
你最终会得到:
(1)
x--x--x--x--x--x--x master
\ \
y--y Y'--y'--y' dev
(2) (5)
(dev1)
这会将您的初始dev
分支分成两部分,并仅在dev
之上仅应用最后master
次提交,同时保持第一次dev
次提交不变,由分支dev1
引用。
您可以尝试:
git rebase -p --onto master `Y^` dev
查看是否保留y
(即Y^
)与新重新定位的Y'
之间的关系。但我怀疑这是可能的。
-p
适用于--preserve-merge
。
答案 1 :(得分:2)
使用my和VonC的答案提供了更多自动化解决方案:
git checkout -b tmp Y
git merge master
git reset --soft HEAD^^
git rev-parse master > .git/MERGE_HEAD
git commit -C Y
git checkout -
git rebase --onto tmp Y
git branch -d tmp
Y - 是要扩展的合并提交。
它的工作原理如下:
x--x--x--x--x--x--x master
\ \
y--y--Y--y--y dev
x--x--x--x--x--x--x master
| \
\ Y tmp
\ / \
y--y y--y dev
x--x--x--x--x--x--x master
| \ \
\ Y-----Y' tmp
\ / \
y--y y--y dev
x--x--x--x--x--x--x master
| \
| -------Y' tmp
\ /
y--y--Y--y--y dev
x--x--x--x--x--x--x master
| \
| -------Y' tmp
\ / \
y--y y--y dev
x--x--x--x--x--x--x master
\ \
y--y--------Y'--y--y dev
答案 2 :(得分:1)
我最终做了以下事情:
git rebase -i -p Y^
在文件中,在合并行之后添加以下行(可能在第一行之后):
exec sh -c "git merge master; git reset --soft HEAD^^; git rev-parse master > .git/MERGE_HEAD; git commit -C `git rev-parse HEAD`"