I have made a wrong merge in git and want to remove the past history about the merge from the local and one of the remote repositories. The figure shows the branch and commit history.
Here, prod
branch contains some branch-specific information (say, db.yml
). I have wrongly merged the prod
branch to master
. As a result, the remote repository of master
now contains all the past commits between C and W. What I wanted was to keep the history of master
clean of change of db.yml
in prod
branch.
In the figure above, what I want is to remove the indicated brown line so that the commit before X in master
branch is commit B as far as the master
branch is concerned, and the remote repository of master
should not know of prod
branch, which was branched out after commit B.
In other words, I want to remove the merge history from commit W to X in master
branch only (which has been pushed to master
repository), while I want to keep commits C to W in prod
branch (which has a separate remote repository). In this case, a simple strategy of git rebase
as explained in the past answer like this does not seem to work well. Or, is there a way?
How can I achieve this?
git checkout -B master B # re-hang the `master` label on the commit before the oops
git cherry-pick Y # make the history it should have
git checkout -B prod W # likewise with `prod`: back to before the oops
git merge master # make the history it should have
Unless you're in the habit of doing what often get called "evil merges", merges with unrelated changes mixed in, you don't want to keep X at all. It's the merge from prod
to master
.
git push --force-with-lease origin master # overwrite if nothing's changed since
and likewise with prod
if that lives there too.