In Git when I have commits eg. A - B - C and I want to edit the B commit, I
- use
git rebase -i <A-commit-hash>, - in the list I write
editcommand in front ofBcommit, - git rebase stops right after
Bcommit so I can fix anything I want usinggit commit --amend, - and then I continue using
git rebase --continue.
As far as I know this is the best practice how to do this. With this method I can edit any commit in the past (as long as it hasn’t been pushed to remote branch yet), and moreover with -p flag I can even preserve the merges. This is just great.
My current problem is: I did a mistake (typo) on one line in a merge commit (while resolving a conflict when merging two branches).
I’d like to fix it but I don’t know how to make git rebase to stop at a merge commit. The git rebase -p -i <blah> list ignores merge commits, so I cannot write edit command in front of it and make the git rebase stop there to let me edit it.
Any help please?
I just want to fix this line in the merge commit while preserving all the commits (and merges) after it.
Thanks.
Updated answer for 2020:
You can force
git rebase -ito stop at the merge commit via thebreakcommand (added in Git 2.20). You can then edit the merge commit as desired viagit commit --amend.Detailed steps:
git rebase -i --rebase-merges $ancestor_of_merge_commitbreak(orb).git commit --amendto edit the merge commit as desired.git rebase --continuewhen you are done editing the merge commit.Alternative approach if you do not have any merge commits after the commit you want to edit:
git rebase -i $id_of_merge_commitbreak(orb).git commit --amendto edit the merge commit as desired.git rebase --continuewhen you are done editing the merge commit.Original answer from 2012 (pre-
break):Git does not make it easy to do interactive rebases when merges are involved. The
-poption uses the-imechanism internally, so mixing the two doesn’t really work.However,
git rebaseis just an automated way to do lots of cherry-picks. You can replicate its behavior by manually cherry-picking to get a bit more control over the process. It’s less convenient and more prone to human error, but possible.This is the approach I suggest:
git rebaseto get to the commit after the merge (the child of the merge)git reset --hard HEAD^to manually get to the mergegit commit --amendto repair the mergegit cherry-pickto get back to the commit after the mergegit rebase --continueto finishHere are the specific steps:
deadbeef.facef00d.git rebase -i deadbeef.facef00dfor editing.facef00d, rungit reset --hard HEAD^. You should now be atdeadbeef(git rev-parse HEADshould printdeadbeef).git addto stage them.git commit --amendto fuse the staged fix with the bad merge commit. The result will now have a different SHA1 (notdeadbeef).git cherry-pick facef00dto apply the changes made byfacef00dto the fixed merge commit.git rebase --continueto finish.