0

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.

enter image description here

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?

4
  • So you want to reset master to B and prod to W? Commented Aug 27, 2021 at 0:44
  • No, I want to keep the current states of master and prod if possible. Certainly prod branch must stay at the current state. Commented Aug 27, 2021 at 1:01
  • 2
    You can't both alter the master history and keep it the same. Saying you want the line some tool draws to be gone doesn't help anybody. Make the history you want, put the labels where they belong, push them. Done. But the history you want is not the history you have, so it's not going to be the current one. Commented Aug 27, 2021 at 2:15
  • @jthill Sure, thanks for clarification. I meant the actual files in HEAD of prod should stay the same, while its history including the commit number can be modified. Based on your answer (which is great!), I have managed to achieve it. I add a comment about it to your answer. Commented Aug 27, 2021 at 10:18

1 Answer 1

1
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.

Sign up to request clarification or add additional context in comments.

3 Comments

This solves my question! In my case, I want to keep all the files in HEAD of prod. So I replaced git checkout -B prod W and merge with the following sequence: git switch prod, checkout -b tmpx, commit --allow-empty, checkout -B prod <W>, merge --no-ff --no-commit master, checkout tmpx -- ., commit, branch -D tmpx
In the sequence I described in my comment, I created a temporary branch tmpx. Reviewing again, I now guess it is unnecessary and I could have simply used <SHA> of Z like git checkout <SHA_Z> -- .
Yup. You've got it.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.