Nothing ever deletes old commits.1 Rebase makes new commits, but the old commits continue to exist. Having made the new commits, we now tell other people with other Git repositories to get these new commits (or send them to those other people using git push
) ... and then we tell them: and stop using the old commits, as these are new and improved replacement commits.
If you're using git push
to send these commits to some shared repository, you must in general use git push --force
or git push --force-with-lease
to achieve the "and stop using the old commits" part.
What you did instead—you didn't say this, but it's pretty common for people to do this by accident—was to make the new-and-improved commits, send them to another Git repository, and then merge both the old commits and the new-and-improved commits. So you now have both sets in your repository.
To fix this, you must eject the merge commit itself from the set of commits you're using. That is, you want to "remove" the merge. As we already noted, that's literally impossible, but you don't have to eradicate the merge commit from your repository; you merely have to stop using it.
The Git command that lets you stop using some particular commit is git reset
. There are some major drawbacks to using git reset
:
To stop using some commit, you must also stop using all subsequent commits on that branch.
If other people (other Git repositories) have that commit, they can give it back to your Git which will happily add it back: Git just loves to add commits, and is reluctant to stop using commits, which is why merge is easy and reset is hard.
But if you've made sure that you have no uncommitted work, you can safely run git reset --hard
now. Run git log --graph
(or see Pretty Git branch graphs) to verify that the merge commit is the tip of the branch, and to see whether the first parent of the merge is the commit you want as the new tip (this seems likely), or whether the second parent of the merge is the one you want as the new tip (less likely but possible). Then:
git reset --hard HEAD~1
will move the branch name back to the first parent of the current commit. If that's not the correct commit—if you needed the second parent—you will have instead run:
git reset --hard HEAD^2
(or in CMD.EXE
, git reset --hard HEAD^^2
). You must carefully view the commit graph first (see the linked question and its answers) to verify that the merge commit is in fact at the tip of the current branch, and that the first or second parent of the merge commit is the commit you want at the tip.
If these aren't the case, consider running:
git log --decorate --oneline --graph
and cutting-and-pasting some of the output (the part with the commits in question) into your question.
1This isn't strictly true, but there's no "remove a commit" command. Instead, we abandon old commits—stop using them—and eventually Git decides that they are not just not being used now, but can't even be found, and Git then eventually removes them on its own. Or, sometimes it doesn't. We don't really control this unless we dive deep into maintenance Git commands.