>问题
假设我已经在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']
是新的合并提交。(顺便说一下,我不介意它是新的。
您可以使用交互式变基:
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
。
-p
是--preserve-merges
的简写,它将阻止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
告诉您变基成功。
如您的问题所示,当您在测试分支中进行 c4 提交并将其合并到主分支时,快进模式只会将主引用移动到 c4,为什么您认为您会丢失分支历史记录并故意使用 --no-ff 选项?
关于您尝试的内容,似乎您对主分支时间线的时间线进行了修改,因此提交图是一个明显的结果。