修改先前合并分支的过去提交,同时保留分支历史记录
Amend a past commit from a previously merged branch, while keeping branch history
问题
说我在master
上做了一些工作:
c1 <- c2
^
master
此时,我分支,做一些更多的工作:
test
v
c3 <- c4
c1 <- c2 /
^
master
然后执行 git merge --no-ff
(--no-ff
以保留分支历史记录):
test
v
c3 <- c4
c1 <- c2 / \ [c5]
^
master
([c5]
是合并提交)
然后我删除了 test
分支,以为我已经完成了它。但是,我发现,毕竟我在test
上所做的工作有问题。我需要修改 c3
,但 不会损害分支历史。
我尝试过的事情
我的尝试
我git checkout c3
;然后改我需要改的,然后git commit --amend
。然后我 checkout
master
分支,和 git branch temp c3
。然后我 git rebase --preserve-merges temp
:这给了我一个合并冲突,我修复了它,然后 git add <file>
和 git rebase --continue
。
但是,当我使用 git log --oneline --graph
查看分支历史记录时,我看到如下内容:
* [c5]
|\
| * c4
|/
* c3'
* c2
* c1
它应该看起来更像这样:
* [c5]
|\
| * c4
| * c3'
|/
* c2
* c1
其中 c3'
是修改后的提交。
我怎样才能摆脱 git
的这种行为?
蒂姆的建议
git checkout c3
git checkout -b test
git commit --amend
git checkout master
git reset --hard c2
git merge --no-ff test
不幸的是,这似乎不起作用,因为我们输了 c4
。 (蒂姆,如果我误解了你的回答,请纠正我。)git log --oneline --graph
的结果分支历史如下:
* [c5]
|\
| * c3'
|/
* c2
* c1
其中 [c5']
是一个新的合并提交。 (顺便说一句,我不介意它是新的。)
如你的问题所示,当你在test分支中提交c4并将其合并到master分支时,快进模式只会将master引用移动到c4,你为什么认为你会丢失分支历史并使用--no-ff 选项是故意的?
关于你的尝试,似乎你对主分支时间线的时间线进行了修改,所以提交图是一个明显的结果。
您可以使用交互式变基:
git checkout master
git rebase -i c2
这应该打开一个编辑器,每次提交一行。将 c3
行中的 pick
更改为 edit
。保存并关闭。现在 git 将您倒回到 c3
并将在那里停下来让您进行编辑。改你想改的,用
修改
git commit --amend
git rebase --continue
我似乎找到了答案!谢谢你,蒂姆,给了我尝试 --interactive
变基的灵感。
基本上,答案在于做一个git rebase -p -i <root>
;我在分支历史分支 <root>
之前调用提交。在问题的假设情况下,<root>
是 c2
.
对于 --preserve-merges
,-p
是 shorthand,这将阻止 git rebase
删除合并提交。
编辑器会弹出如下内容:
pick c3 <message>
pick c4 <message>
pick [c5] <message>
将 c3
之前的 pick
更改为 edit
以便您拥有:
edit c3 <message>
pick c4 <message>
pick [c5] <message>
保存并退出。进行您想要进行的更改,添加它们,然后 git commit --amend
。在此之后,您需要git rebase --continue
继续变基。
在此期间您可能会遇到合并冲突。只需修复冲突,git add
更改的文件以将冲突标记为已修复,然后 git rebase --continue
。重复此操作,直到 git
告诉您变基已成功。
问题
说我在master
上做了一些工作:
c1 <- c2
^
master
此时,我分支,做一些更多的工作:
test
v
c3 <- c4
c1 <- c2 /
^
master
然后执行 git merge --no-ff
(--no-ff
以保留分支历史记录):
test
v
c3 <- c4
c1 <- c2 / \ [c5]
^
master
([c5]
是合并提交)
然后我删除了 test
分支,以为我已经完成了它。但是,我发现,毕竟我在test
上所做的工作有问题。我需要修改 c3
,但 不会损害分支历史。
我尝试过的事情
我的尝试
我git checkout c3
;然后改我需要改的,然后git commit --amend
。然后我 checkout
master
分支,和 git branch temp c3
。然后我 git rebase --preserve-merges temp
:这给了我一个合并冲突,我修复了它,然后 git add <file>
和 git rebase --continue
。
但是,当我使用 git log --oneline --graph
查看分支历史记录时,我看到如下内容:
* [c5]
|\
| * c4
|/
* c3'
* c2
* c1
它应该看起来更像这样:
* [c5]
|\
| * c4
| * c3'
|/
* c2
* c1
其中 c3'
是修改后的提交。
我怎样才能摆脱 git
的这种行为?
蒂姆的建议
git checkout c3
git checkout -b test
git commit --amend
git checkout master
git reset --hard c2
git merge --no-ff test
不幸的是,这似乎不起作用,因为我们输了 c4
。 (蒂姆,如果我误解了你的回答,请纠正我。)git log --oneline --graph
的结果分支历史如下:
* [c5]
|\
| * c3'
|/
* c2
* c1
其中 [c5']
是一个新的合并提交。 (顺便说一句,我不介意它是新的。)
如你的问题所示,当你在test分支中提交c4并将其合并到master分支时,快进模式只会将master引用移动到c4,你为什么认为你会丢失分支历史并使用--no-ff 选项是故意的?
关于你的尝试,似乎你对主分支时间线的时间线进行了修改,所以提交图是一个明显的结果。
您可以使用交互式变基:
git checkout master
git rebase -i c2
这应该打开一个编辑器,每次提交一行。将 c3
行中的 pick
更改为 edit
。保存并关闭。现在 git 将您倒回到 c3
并将在那里停下来让您进行编辑。改你想改的,用
git commit --amend
git rebase --continue
我似乎找到了答案!谢谢你,蒂姆,给了我尝试 --interactive
变基的灵感。
基本上,答案在于做一个git rebase -p -i <root>
;我在分支历史分支 <root>
之前调用提交。在问题的假设情况下,<root>
是 c2
.
对于 --preserve-merges
,-p
是 shorthand,这将阻止 git rebase
删除合并提交。
编辑器会弹出如下内容:
pick c3 <message>
pick c4 <message>
pick [c5] <message>
将 c3
之前的 pick
更改为 edit
以便您拥有:
edit c3 <message>
pick c4 <message>
pick [c5] <message>
保存并退出。进行您想要进行的更改,添加它们,然后 git commit --amend
。在此之后,您需要git rebase --continue
继续变基。
在此期间您可能会遇到合并冲突。只需修复冲突,git add
更改的文件以将冲突标记为已修复,然后 git rebase --continue
。重复此操作,直到 git
告诉您变基已成功。