Suppose I have a repository like this:
I --- C --- M master
\ /
`- A -´ topic
where M
is a merge commit incorporating topic
into master
.
Later I find a bug in C
, so I make a commit fixing it on the master
branch, on top of M
:
I --- C --- M --- C1 master
\ /
`- A -´ topic
but ideally I would like the history to look like this:
I --- C --- C1 --- M master
\ /
`- A --------´ topic
How can I rewrite the history so that C1
appears before the merge M
?
I could remove M
, apply the patch made by C1
, and merge topic
into master
again, resolving all the conflicts again, but I'd like to avoid the effort, and I'd prefer to preserve the original commit information (author, date, etc.) if possible, which rules out doing git commit
again. I hope it's possible with git rebase
, but I failed, with either one or both of -p
and -i
.
The best way I've found is:
git checkout -b tmp master^^
# Now tmp is on top of C
git cherry-pick master
# Now tmp is on top of C1', a copy of C1
git rebase -p tmp master
# Now master is on top of a merge commit from C1' and A
git branch -d tmp
I don't know why git rebase
cannot do this all at once without git cherry-pick
, but at least I know this works.