yelliver yelliver - 3 months ago 8
Git Question

Delete commit which is merged into main branch

How to delete this purple commit and the "Merge branch..." commit.
I try to using "git rebase -i HEAD~x" but not work.

enter image description here

Answer

You can do this kind of magic with git fast-export (after you made a backup of your working copy): Run git fast-export --no-data --all --full-tree > all_commits in your working copy. Then you open the file all_commits in a text editor, and search for "initial commit". The environment around it should look like this:

commit refs/heads/master
mark :110
author Foo Bar <foobar@example.org> 1462192582 +0100
committer Foo Bar <foobar@example.org> 1462192582 +0100
data 14
Initial Commit
deleteall
M 100644 b346ed4d2db0c8110fe3104bd155a413b878527c some/file

commit refs/heads/master
mark :111
author Foo Bar <foobar@example.org> 1462192582 +0100
committer Foo Bar <foobar@example.org> 1462192582 +0100
data 21
Merge branch 'master'
from :109
merge :110
deleteall
M 100644 b346ed4d2db0c8110fe3104bd155a413b878527c some/file
M 100644 4d9af842ccf23b883b234f5ae93d71f11fa285de some/other_file

commit refs/heads/master
mark :112
author Foo Bar <foobar@example.org> 1462192582 +0100
committer Foo Bar <foobar@example.org> 1462192582 +0100
data 14
Did some stuff
from :111
deleteall
M 100644 b346ed4d2db0c8110fe3104bd155a413b878527c some/file
M 100644 d6a0ad80d11b9d376c23d17300ce95d724d050e7 some/other_file

You cut out that commit, by removing the commit block and adjustment of the references (mark places a reference to a commit to identify it later, and from or merge identify the parents of a commit):

commit refs/heads/master
mark :111
author Foo Bar <foobar@example.org> 1462192582 +0100
committer Foo Bar <foobar@example.org> 1462192582 +0100
data 21
Merge branch 'master'
from :109
deleteall
M 100644 b346ed4d2db0c8110fe3104bd155a413b878527c some/file
M 100644 4d9af842ccf23b883b234f5ae93d71f11fa285de some/other_file

commit refs/heads/master
mark :112
author Foo Bar <foobar@example.org> 1462192582 +0100
committer Foo Bar <foobar@example.org> 1462192582 +0100
data 14
Did some stuff
from :111
deleteall
M 100644 b346ed4d2db0c8110fe3104bd155a413b878527c some/file
M 100644 d6a0ad80d11b9d376c23d17300ce95d724d050e7 some/other_file

Than you import your changed stream with git fast-import --force < all_commits. After this operation, the offending commit is gone.

When something went wrong, you can recover your original commits with git fast-import --force < all_commits.backup, but it is not a bad idea to create a backup before this operation.