How to remove a commit that has already been pushed?
You just ran git push, sending your changes to your remote server, now you realize there’s a problem with one of those commits. You’d like to undo that commit.
A git reset
could work, but it would also remove the commit from the history of the remote server. By force pushing the new history, you could potentially lose the work of your coworkers if they have already pulled from the remote server.
A git revert
is a safer alternative as it creates a new commit that undoes the changes made in the commit you want to remove. This way, you can push the new commit to the remote server without losing any history.
Setup
Let’s add three commits to your repository.
We’ll start with a clean repository:
alina
alina git:( main ) git status
On branch main
Your branch is up to date with 'origin/main'.
nothing to commit, working tree clean
alina git:( main ) █
And now we’ll add one commit:
alina
alina git:( main ) echo "add line 1" >> README.md
alina git:( main ) git add README.md
alina git:( main ) git commit -m 'add line 1'
[main d8aa742] add line 1
1 file changed, 2 insertions(+), 1 deletion(-)
alina git:( main ) █
This gives us the following commit graph:
And we’ll repeat that process with two other commits (we’ll omit the terminal output and commit graph for brevity).
Eventually, we’ll have the following commit graph:
And the content of the README.md
file will be:
alina
alina git:( main ) cat README.md
# arenas
GitPowerUp Repository: arenas
add line 1
add line 2
add line 3
alina git:( main ) █
Let’s suppose that at this stage, you push your commits to the remote server:
alina
alina git:( main ) git push
Enumerating objects: 11, done.
Counting objects: 100% (11/11), done.
Delta compression using up to 8 threads
Compressing objects: 100% (6/6), done.
Writing objects: 100% (9/9), 688 bytes | 688.00 KiB/s, done.
Total 9 (delta 2), reused 0 (delta 0), pack-reused 0
remote: . Processing 1 references
remote: Processed 1 references in total
To ssh://remote.mygit.com/gitpowerup/arenas.git
4dc6afc..4282fc8 main -> main
alina git:( main ) █
The commit graph will show that your commits landed on the remote server:
Now it would be frowned upon if you were to rewrite the history of the remote server, so you need to find a way to undo the commit without rewriting history.
Solution
Let’s take a look at your list of commits:
alina
alina git:( main ) git log --oneline
4282fc8 (HEAD -> main, origin/main, origin/HEAD) add line 3
1b0ef4a add line 2
d8aa742 add line 1
4dc6afc Initial commit
alina git:( main ) █
The git revert
command will create a new commit that undoes the changes made in the commit you want to remove.
If you want to revert the last commit, you can use the HEAD
reference (or the commit hash) as the argument for the git revert
command:
alina
alina git:( main ) git revert HEAD
... opens the associated editor for you to comment ...
alina git:( main ) █
This command will add a new commit to your history that reverts the changes made in the last commit:
And your README.md
file will be back to its previous state:
alina
alina git:( main ) cat README.md
# arenas
GitPowerUp Repository: arenas
add line 1
add line 2
alina git:( main ) █
If you want to remove the add line 2
commit as well, you can use git revert
again, this time using the SHA of the commit that added that line:
alina
alina git:( main ) git revert 1b0ef4a
... editor opens up ...
alina git:( main ) █
Here is your updated README.md
file:
alina
alina git:( main ) cat README.md
# arenas
GitPowerUp Repository: arenas
add line 1
alina git:( main ) █
And finally, you can revert the addition of the first line:
alina
alina git:( main ) git revert d8aa742
... editor opens us
alina git:( main ) █
The commit graph shows that all these reverts have added new commits on top of the existing ones:
And the README.md
file is back to its original pristine state:
alina
alina git:( main ) cat README.md
# arenas
GitPowerUp Repository: arenas%
alina git:( main ) █
This time, it is safe to push as there is no history rewriting involved:
alina
alina git:( main ) git push
Enumerating objects: 11, done.
Counting objects: 100% (11/11), done.
Delta compression using up to 8 threads
Compressing objects: 100% (5/5), done.
Writing objects: 100% (9/9), 832 bytes | 832.00 KiB/s, done.
Total 9 (delta 2), reused 2 (delta 0), pack-reused 0
remote: . Processing 1 references
remote: Processed 1 references in total
To ssh://remote.mygit.com/gitpowerup/arenas.git
4282fc8..b009973 main -> main
alina git:( main ) █
The only side effect is that the git history is a bit messy, but that is a small price to pay for pushing to the remote too fast.