Reverting an old merge commit files without effecting subsequent commits

Viewed 81

I need to revert a very old merge commit from the main branch.

The thing is, I don't want the revert operation to effect the other changes which was made from that point on on the main branch.

As far as I understand, if I use:

git revert -m 1 [hash merge commit]

It would revert to the parent commit of the merge commit and would remove all the changes which were added later.

The merge commit involves multiple files.

Is there a way to achieve this with a built in command in git other than going file by file?

1 Answers

You could rebase interactively, starting from the commit before the merge commit, and remove the commits for that merge commit.

Let's take this history from some branch feature/rebase-test:

* 1ff3147 - (tag: v0.4.3, origin/master, origin/HEAD, master) Add test to show URLs with port work
* a686fbf - (tag: v0.4.2) Enable setting custom RequestHandler
* f682d20 - Add php 7.4 to Travis
* 0973364 - Make code coverage script CLI runnable
* cb106fc - Add composer.phar to gitignore
*   1d89b5e - (tag: v0.4.1) Merge pull request #62 from mvdbos/fix/event-dispatcher
|\
| * 3376b9c - Revert to the legacy EventDispatcher
|/
* f761a2c - Update README badges
*   b8447e6 - (tag: v0.4) Merge pull request #60 from mvdbos/feature/cleanup
|\
| * e278cde - Simplify build and clean up use statements
|/
*   ac6af67 - Merge pull request #59 from mvdbos/feature/update-scrutinizer

Now let's say I want to remove b8447e6 (and therefore e278cde, which is part of that merge commit).

I could do git rebase --rebase-merges --onto ac6af67 f761a2c feature/rebase-test). This would take everything from f761a2c forward until the tip of feature/rebase-test and rebase it onto ac6af67, which is the commit just before the merge we want to get rid of.

In my case that resulted in a few conflicts, and after solving that, my history looks like this:

* d7e5919 - (HEAD -> feature/rebase-test) Add test to show URLs with port work
* 0d8e15f - Enable setting custom RequestHandler
* ce365b0 - Add php 7.4 to Travis
* 42d6f59 - Make code coverage script CLI runnable
* ad0c861 - Add composer.phar to gitignore
*   3292f4c - Merge pull request #62 from mvdbos/fix/event-dispatcher
|\
| * 3e2ceef - Revert to the legacy EventDispatcher
|/
*   ac6af67 - Merge pull request #59 from mvdbos/feature/update-scrutinizer

Note that the merge commit is gone and that the structure of the following commits is kept as it was, including merge commits. This is due to the --rebase-merges flag of the rebase command.

One caveat: as you may have noticed, all commits after ac6af67 have a new hash (they are really new commits). This means that the tags that existed in our previous history, don't point to those new commits. They do still exist though, so nothing will be broken. They just point to a history that still contains that merge commit you wanted to remove. Can't judge if that would be a problem for you.

Related