撤销Git合并,但保留后续更改并重写历史记录

9

我有很多分支,每个分支都有不同的特性。通常我会有一些额外的分支"not_master",其中包含master和feature A,如下所示:

(not_master)     a--b--c--d--e---M--x--y--z
(feature A)           --h--i--j-/

有时候我希望取消合并功能A,但保留“not_master”中的提交。
换句话说,我想要这样:
(not_master)     a--b--c--d--e--x--y--z

我发现我可以执行 git revert -m 1 M,这将在末尾添加一个撤消我的更改的提交,但我不想这样做,因为这些提交尚未发布,所以添加更多提交会使历史记录更难以阅读。
其他人建议只需执行 git reset --hard M,但这将放弃 x、y、z 的更改。我是不是完全想错了?我应该只需执行 git reset --hard M 并挑选 x、y、z 吗?
1个回答

10

git rebase可以实现你所需的功能。使用git rebase -i <commit e>应该会有所帮助:它将打开一个编辑器,你需要删除合并提交并保存。

你还可以直接指定将x..z变基到e上,但是处理命令行语义有点困难。如果我正确地阅读了手册,那么应该是git rebase --onto <commit e> <commit M> not_master

编辑:测试过,似乎可以工作:

mkdir foo; cd foo
git init
touch initial
git add initial
git commit -m 'initial'
git checkout -b topic
touch topic
git add topic
git commit -m 'topic'
git checkout master
touch master
git add master
git commit -m 'master'
git tag pre_merge
git merge topic
git tag merge
touch post_topic
git add post_topic
git commit -m 'post topic'
git rebase --onto pre_merge merge master

导致了历史上的结果

initial -- master -- post topic  (master)
      \
       \-- topic                 (topic)

嗯,我尝试过这个,但git rebase实际上不会显示合并提交。所以基本上我必须在git rebase中追踪h、i、j并将它们删除,这是我考虑过的... - KarateSnowMachine
2
啊,真烦人。试试我添加的备用命令。(可能还需要 --force-rebase)。 - wnoise
哇,太神了,就像魔法一样。非常感谢你的尝试!我试图阅读 git-rebase 的手册,但我觉得我有点崩溃了。我想我会开始使用 rebase 而不是合并这样的事情,这样我就不会有所有这些交错的提交了... - KarateSnowMachine

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接