Search code examples
gitgit-mergegit-rebase

Remove git merges from the middle


We maintain a branch structure with a merge workflow. As a result our master branch commit hierarchy looks like this.

Expected hierarchy

However, since we use Gitlab community edition which doesn't squash and rebase merges, sometimes developers forget to do one or the other and merge commits which look like this.

Bad merges

The usual way I follow to recover from this is to reset master to the last good commit before these merges and then replay every merge (after rebasing and squashing correctly) to merge them.

A better way may be to use the git rebase --onto command to replay the good merges after the bad merges have been fixed. However, I have been unable to figure out the correct way to do this. What I do is:

  1. Reset master branch to the commit for the last good merge.
  2. Rebase bad commit (not squashed-rebased) on top of the rebased branch.
  3. Merge the squashed-rebased commit on the rebased branch.
  4. Repeat the process for any other bad commits.
  5. Finally replay all good merges in the same way as in steps 2-3.

I tried using git rebase -ip --onto <last_good_commit> to replay my good merges in step 5 but that seems to exchange the order of parents for the commit. Anyone have a good way of improving my workflow so that I don't have to replay every single merge manually?


Solution

  • The answer by @VonC was almost correct. I had to modify the rebase command as git rebase -ipm --onto <last_good_commit> <first> <yourBranchToReplay> and it rebased all remaining merges correctly on the fixed merges.