In Git when I have commits eg. A - B - C
and I want to edit the B
commit, I
git rebase -i <A-commit-hash>
,edit
command in front of B
commit,B
commit so I can fix anything I want using git commit --amend
,
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.
You can force git rebase -i
to stop at the merge commit via the break
command (added in Git 2.20). You can then edit the merge commit as desired via git commit --amend
.
Detailed steps:
git rebase -i --rebase-merges $ancestor_of_merge_commit
break
(or b
).Stopped at fb91fab (Merge branch 'foo' into bar)
git commit --amend
to edit the merge commit as desired.git rebase --continue
when 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_commit
break
(or b
).Stopped at fb91fab (Merge branch 'foo' into bar)
git commit --amend
to edit the merge commit as desired.git rebase --continue
when you are done editing the merge commit.break
):Git does not make it easy to do interactive rebases when merges are involved. The -p
option uses the -i
mechanism internally, so mixing the two doesn't really work.
However, git rebase
is 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 rebase
to get to the commit after the merge (the child of the merge)git reset --hard HEAD^
to manually get to the mergegit commit --amend
to repair the mergegit cherry-pick
to get back to the commit after the mergegit rebase --continue
to finishHere are the specific steps:
deadbeef
.facef00d
.git rebase -i deadbeef
.facef00d
for editing.facef00d
, run git reset --hard HEAD^
. You should now be at deadbeef
(git rev-parse HEAD
should print deadbeef
).git add
to stage them.git commit --amend
to fuse the staged fix with the bad merge commit. The result will now have a different SHA1 (not deadbeef
).git cherry-pick facef00d
to apply the changes made by facef00d
to the fixed merge commit.git rebase --continue
to finish.