How to re-merge an already merged branch?
Git stores snapshots and detects changes on the fly, so the way to work with the difference between a bad commit and a good one is to record the good as a descendant the bad—pretty much the same as anything, come to think of it. Use git reset --soft
to tell git the correct ancestry:
git checkout badmerge^1 # generate the right result
git merge badmerge^2
... Fix conflicts ...
git commit
git reset --soft badmerge # as an improvement on the wrong result
git commit
git checkout master # merge the difference now that git sees it
git merge HEAD@{1} -m "applying corrections to a bad merge"
You can try by a cherry-pick:
git checkout master
git cherry-pick B..[last_commit_of_C*]
Git may ask you to confirm the cherry-pick since the commits are in the ancestors.
Ideally, we would take all the changes in C*, apply them to master and resolve all conflicts.
No, ideally you would rewind time, do the merge as it was back then (but correctly, this time), then reapply the F*
changes and end up with a correct master
.
You can do it like this:
git checkout missing-commits
git checkout -b correct-merge
git merge D # do it right, this time around!
git checkout master
git checkout -b correct-master
git rebase --onto correct-merge wrong-merge correct-master # have fun with the mother of all rebases!
If you manage to handle all the conflicts during the rebase, you will end up with exactly what you wanted, originally, in the branch correct-master
.
Since you do not want to change history, you could then create a big patch and apply that to your current master
, but I like this approach more (assuming you did all your work in your working directory yourrepos
):
cd yourrepos ; git checkout correct-master ; cd ..
cp -a yourrepos newrepos
rm -rf newrepos/.git
cd yourrepos ; git checkout master ; cd ..
cp -a yourrepos/.git newrepos/
Now, when you enter newrepos
and do a git status
, you will be on branch master
and will see precisely all changes between master
and correct-master
, as if you had applied a patch. It will catch deleted files, new files, changed files, changed permissions, changed symlinks and so on.
Ideally, if everything went right, it will show exactly the missing commits from C
. Use your favourite variant of git add
and finally a nice git commit
(or several, if you prefer), and you're done. No history has been rewritten.