从以前合并的分支修改过去的提交,同时保留分支历史记录



>问题

假设我已经在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 选项?

关于您尝试的内容,似乎您对主分支时间线的时间线进行了修改,因此提交图是一个明显的结果。

最新更新