How to revert to several older commits including merge but have one commit on top of the head of reverted commit? [closed]

Solution for How to revert to several older commits including merge but have one commit on top of the head of reverted commit? [closed]
is Given Below:

I have a list of commits like this:

Author: xyz
Date:   Fri Jul 30 11:48:40 2021 -0700

    update tests

commit 76810c2bdf91cd84661fabb06f00f37fc0e6b264
Author: abc
Date:   Thu Jul 29 16:38:33 2021 -0700

    fix for issue

commit b9a1642c3d778524291c98895425aa0248ed5766
Merge: baeb6428 6b722171
Author: abc
Date:   Thu Jul 29 16:36:58 2021 -0700

    Merge branch

commit 6b722171718f7aa70236613c544d8ca9f6cdeea9
Author: abc
Date:   Thu Jul 29 17:15:02 2021 +0000

    Use new type

commit baeb642886c19135c6057fba94849768b5ffc5a3
Author: abc
Date:   Wed Jul 28 16:24:10 2021 -0700

    old commit 

I want to go back to old commit but have one commit 76810c2bdf91cd84661fabb06f00f37fc0e6b264 included. How should I do that?

I tried git revert <hash> for each one of the commits manually and git revert -m 1 <merge hash> for merge commits but it is not working as expected. Also, I have a long list of reverts to do and it is a tedious task to do it manually. Is there a simpler way to do this?

This scenario sometimes happens in our team on release/integration branches, where the release of certain features is to be aborted/canceled but those have been already committed or merged on the release/integration branch.

From your comment:

I want A <- B <- C <- D to be like B <- D

Instead of trying to find a solution with git revert, we’d rather do:

  1. Create a new branch on D
    • See How do I create a new Git branch from an old commit?
  2. If B is a single or small set of commits, just git cherry-pick it/them

Following the hashes on your example, it would be:

# git checkout -b <new-branch-name> <old commit>
$ git checkout -b new-branch baeb642886c19135c6057fba94849768b5ffc5a3

# git cherry-pick <specific commit>
$ git cherry-pick 76810c2bdf91cd84661fabb06f00f37fc0e6b264

# make new branch available to rest of team
$ git push -u origin new-branch

Now we have new-branch which is based on old commit + that one commit on top of it. There might be conflicts on cherry-pick if the commit you are cherry-picking depends on changes from C which isn’t included here anymore.

D -> C -> B -> A [old-branch]
   -> B [new-branch]

Note that nothing’s really reverted here, as the old-branch with the commits you don’t want anymore is still there. But at least here, people’s local copies have fewer chances of getting messed up since they simply need to checkout this new-branch. (We usually keep old-branch for a while as a reference, because sometimes people change their minds…).

To complete a revert operation, we can then simply delete old-branch which deletes all those commits you didn’t include anymore in new-branch. This has the same destructive effect as git revert, so take care that you really don’t need any of those commits anymore, especially merged branches (you might want to re-create those branches).