Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Undo a Git merge, but keep later changes, and rewrite history

I have a bunch of branches, each with different features. Usually I'll have some extra branch "not_master" which contains master+feature A like so:

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

Sometimes I want to unmerge feature A, but keep commits x,y,z in "not_master".

In other words, I would like this:

(not_master)     a--b--c--d--e--x--y--z

I see that I can do a git revert -m 1 M which will add a commit to the end that reverts my changes, but I don't really want to do that since these commits haven't been published yet so adding more commits makes the history even harder to read.

Others suggest just doing a git reset --hard M, but that will dump the changes of x,y,z. Am I just thinking about this the completely wrong way? Should I just git reset --hard M and cherry pick x,y,z?

like image 453
KarateSnowMachine Avatar asked Jan 25 '11 20:01

KarateSnowMachine


1 Answers

git rebase will do what you want. git rebase -i <commit e> should work: it will open an editor, and you delete the merge commit and save.

You should also be able to directly specify rebasing x..z onto e, but sorting out the semantics of the command-line is a bit hairy. If I'm reading the man page right, It should be git rebase --onto <commit e> <commit M> not_master.

EDIT: Tested and appears to work:

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

results in a history of

initial -- master -- post topic  (master)
      \
       \-- topic                 (topic)
like image 164
wnoise Avatar answered Sep 24 '22 01:09

wnoise