Undo, Remove or Revert Specific Git Commits
There's a couple of ways to do this depending on your use case.
We’re going to cover 3 use cases:
- Undo last N commits
- Remove a specific git commit
- Revert a specific commit that was already pushed
The first 2 are meant to be done before you push anything where it’s safe to rewrite history without doing a force push while the last one is ok to do even if you pushed things.
If you want a local demo git repo to follow along, this will set one up:
mkdir -p /tmp/git-delete \
&& cd "${_}" \
&& rm -rf .git A B C \
&& git init \
&& touch A && git add A && git commit -m "Commit A" \
&& touch B && git add B && git commit -m "Commit B" \
&& touch C && git add C && git commit -m "Commit C"
# Undo Last N Commits
This will undo the last commit:
git reset HEAD~1
- Optionally add
--hard
if you want the files in your working directory to be undone too, effectively wiping all traces of that commit’s contents
- Optionally add
You can replace ~1
with the number of commits to go back. For example ~2
will undo the last 2 commits. That means both the 2nd to latest and latest
commits will be undone.
You can always replace HEAD~N
with the GIT_SHA^
too (the ^
is important).
The operation acts the same. You can find the SHA with git log
.
If you happen to want to undo all commits on a specific branch but don’t want
to rm -rf .git
the whole repo you can run git update-ref -d HEAD
.
Optionally run git reset --hard
right after to remove the changes on disk.
# Remove Specific Commit
Let’s say you’ve made 3 local commits that you haven’t pushed yet and now you realize you want to delete only the middle (2nd) commit.
You can do an interactive rebase and drop the commit. I’ve written about using interactive rebase to change commits in the past, this will be similar.
git rebase --interactive HEAD~2
- When prompted, replace “pick” with “drop” for the commit
- It’ll perform the rebase for you automatically after you pick “drop”
Like the first example you can replace HEAD~N
with the GIT_SHA^
.
If you want to delete the oldest commit you can use --root
instead of
HEAD~N
/ GIT_SHA^
.
By the way, before doing any of the above you’ll want to make sure you don’t
already have something running like an active git commit prompt in your
terminal or code editor. If you do it will fail and then you’ll need to
git rebase --abort
and try again. Don’t worry, it won’t break anything if
this happens!
# Revert Pushed Commit
This last one is handy if you’ve commit and pushed something and now realize you want to reverse whatever you did. Maybe you found a bug a few days later.
git revert HEAD~2
- Create your commit message as you see fit (it will be pre-populated)
- Optionally add
--no-commit
to prevent it from auto-creating a commit so you can stage / review / etc. it
In the end this will add a new commit which is why it’s safe to do on pushed
commits. It’s not rewriting history. You can check it out by running git show
afterwards.
Like the other examples you can replace HEAD~N
with the GIT_SHA
but this
time around you don’t want to put the ^
, it will already target the SHA we
want.
If you want to revert the oldest commit, you can use the GIT_SHA
and it will
work out of the box, but you wouldn’t be able to use HEAD~3
(the oldest
commit in our old example).
The video below shows all of the above commands.
# Demo Video
Timestamps
- 1:18 – Resetting the latest commit
- 2:20 – Resetting the latest 2 commits
- 2:50 – Reference by SHA instead of HEAD~N
- 3:27 – Resetting the initial commit
- 4:42 – Deleting 1 specific commit
- 6:10 – Deleting the initial commit
- 6:41 – What if the rebase fails?
- 9:01 – Revert a commit
- 10:12 – Referencing the SHA directly
- 10:35 – Revert without auto-committing it
When was the last time you had to remove a git commit? Let me know below.