Remove merge commit from git
I have a merge commit in a Git repository that I want to delete.
How do I actually remove a commit from git?
I mean DELETE a commit that has no commits after that. I just don't want it to clutter up history (and take up disk space).
Please do not reply with anything like "git -i rebase", as you cannot use rebase to remove a commit without any child commits.
0 <-this is now HEAD and master | | this is a different merge between the same branches, master and hotfix-1 | / 0 0 <-THIS is the commit I want to DELETE (incorrect merge) |\ /| | X | |/ \| 0 0 | | | | | | | 0 | | | | | | 0 0 <- this is start of branch hotfix-1 | / | / |/ 0 |
Please do not reply with something like "git reset --hard HEAD ~ 1" as it does not remove the commit for commits:
user@host /dir/subdir (master) $ git checkout b605a0dd5e12e65081a2d8ffe7c905617b210605 Note: checking out 'b605a0dd5e12e65081a2d8ffe7c905617b210605'. You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branches by performing another checkout. If you want to create a new branch to retain commits you create, you may do so (now or later) by using -b with the checkout command again. Example: git checkout -b <new-branch-name> HEAD is now at b605a0d... Merge branch 'hotfix-1' user@host /dir/subdir ((b605a0d...)) $ git reset --hard HEAD~1 ## TRYING TO DELETE COMMIT HEAD is now at 65e8158 Some commit message user@host /dir/subdir ((Some tag)) $ git checkout b605a0dd5e12e65081a2d8ffe7c905617b210605 Previous HEAD position was 65e8158... Some commit message HEAD is now at b605a0d... Merge branch 'hotfix-1' user@host /dir/subdir ((b605a0d...)) ## COMMIT STILL THERE $
source to share
If the commit doesn't link anything to it, eg. branches or tags, then the commit is not available and is effectively removed from history. This will eventually be garbage collected and physically removed from the repository database.
You can run a garbage collection command by running
git gc --prune=now
to get rid of inaccessible objects.
Note that you don't need to do this at all, as unreachable commits are not pushed anywhere and temporarily exist in your repository. Keeping unreachable commits will help you restore commits in case something went wrong and the industry pointers were missing. Therefore, unless you have memory issues, I personally do not recommend that you prune your repository.
source to share
As I correctly informed you (your dismissive answer), a commit without reference to it can be garbage collected, and there is no "more direct" command to remove a commit than
The problem, of course, is that something is probably still referencing this commit. This "something" is a ref log.
A vanity that insists on eliminating all traces of error is a waste of effort. The problem (such as it) will go away on its own over time (because the reflog will expire and then gc will catch up with the commit), and, at the same time, a single merge join may not even remotely take up significant disk space.
This does not mean that it is impossible, but it is expensive. You can either
(A) Destroy your logs and then run
. Of course, you will need to make sure that any reflog that could indicate an offensive commit is discarded. This is at least the
reflog and reflog for the branch where the merge happened. You will likely lose useful reflog history in the process.
(B) Create a new clone. Assuming you committed the merge before pushing, then the merge commit should not be present at the start. Any new clone will then not contain a commit. (They won't have any history of your reflogs either, so this is really equivalent to (A).)
source to share