Skip to content

Grokem · https://www.grokem.com/programming/version-control/git-undo-last-commit

Version ControlHow-to guide

Undo the last Git commit: reset, revert and restore

Three ways to take back work in Git, and the one question that picks between them: has the commit already been shared?

Grokem Editorial

Editorial desk

Published
  • Beginner
  • 8 min to complete
Tested withGit2.53

Before you start

  • Git installed and a repository with at least two commits
  • A clean working tree, or changes you are happy to lose or keep (check with git status)

Everyone commits the wrong thing sooner or later: a typo in the message, a file that should not be there, a change that belongs on another branch. Git gives you several ways out. Which one is right depends on a single question:

Has this commit left your machine? If you have pushed it, or anyone has pulled it, do not rewrite it. Use git revert. If it only exists locally, git reset is fine.

The example

A history with three commits, the last one a mistake:

text
c2c1377 Add third line (wrong)
a7bcf76 Add second line
dfea50b Add notes

Local commit: keep the changes, redo the commit

git reset --soft HEAD~1 moves the branch back one commit and keeps everything staged, so you can fix the problem and commit again.

bash
git reset --soft HEAD~1
git status --short
text
M  notes.txt

The commit is gone from the log and the change is still staged (M in the left column). Fix what you need and run git commit again. This is the usual answer to "wrong message" or "forgot a file". For just the message of the last commit, git commit --amend is shorter.

Local commit: keep the changes, but unstage them

git reset HEAD~1 (the default is --mixed) also moves the branch back, but leaves the changes in your files, not staged.

bash
git reset HEAD~1
git status --short
text
 M notes.txt

Now the leading space shows an unstaged change. Use this when you want to split one commit into two: stage and commit the parts separately.

Local commit: throw the changes away

git reset --hard HEAD~1 moves the branch back and discards the changes from your files.

bash
git reset --hard HEAD~1
text
HEAD is now at a7bcf76 Add second line

This is the one that destroys work, and it also discards any uncommitted edits. Check git status first. If you regret it, the reflog usually saves you:

bash
git reflog
text
a7bcf76 HEAD@{0}: reset: moving to HEAD~1
821d0e7 HEAD@{1}: commit: again

Each line is a place HEAD has been. Find the hash from before the reset and run git reset --hard 821d0e7 to return to it. Git keeps reflog entries for a limited time (by default 30 days for commits that are no longer on any branch, and 90 for the rest), so act soon.

Shared commit: cancel it with a new one

If the commit has been pushed, use git revert. It creates a new commit that applies the opposite change, so nobody's history is rewritten.

bash
git revert --no-edit HEAD
git log --oneline
text
56419b3 Revert "work on a detached head"
fb58245 work on a detached head
a7bcf76 Add second line
dfea50b Add notes

Both the original and its reversal stay in the log. That is the point: everyone who pulled the original gets the reversal as an ordinary update. To revert an older commit, give its hash: git revert <hash>.

Just one file, not the whole commit

git restore puts files back without touching history.

bash
git restore notes.txt                    # discard uncommitted edits to the file
git restore --staged notes.txt           # unstage the file, keep the edits
git restore --source=HEAD~1 notes.txt    # take the file as it was one commit ago

The first command throws away unsaved edits to that file, so use it deliberately.

Choosing quickly

Situation Command
Wrong message on the last local commit git commit --amend
Redo the last local commit with changes git reset --soft HEAD~1
Split the last local commit git reset HEAD~1
Discard the last local commit and its changes git reset --hard HEAD~1
Cancel a commit that is already shared git revert <hash>
Undo edits or staging of one file git restore [--staged] <file>

When in doubt, make a safety copy first: git branch backup leaves a pointer to where you are, and costs nothing.

Expected result

The unwanted commit is gone from your history (reset) or cancelled by a new commit (revert), and your files are in the state you intended.

Frequently asked questions

I ran git reset --hard and lost work. Can I get it back?

Often yes, if it was committed. Run git reflog, find the commit's hash from before the reset, and run git reset --hard <hash>. Work that was never committed cannot be recovered this way.

What is the difference between reset and revert?

Reset moves the branch pointer back and rewrites history. Revert adds a new commit that cancels an earlier one and leaves history intact, which is why it is the safe choice for anything shared.

References

From Grokem: https://www.grokem.com/programming/version-control/git-undo-last-commit

How did this strike you?

Be the first to react – it is anonymous.

Community

Questions about this?

Ask in Questions and help and get help from other readers.

Ask a questionBrowse Questions and help

Comments (2)

  • Hannah

    What if I have already pushed the commit I want to undo?

    • Grokem Editorial

      Use `git revert`. It adds a new commit that undoes the old one and leaves history as it was, which is safe for a branch other people have pulled. Rewriting pushed history with `reset` forces everyone else to repair their copy.

Choose what we may use. You can change this at any time with “Privacy choices” at the foot of every page. Details are in the Cookie policy and the Privacy policy.

Strictly necessary

Remembers your theme, the lessons you marked as done and this choice. It stays on your device, tracks nothing and cannot be switched off.

Always on
What exactly is collected, and why

Grokem’s own counts

Collects
The pages you open and how long you stay, how far you scroll, where you came from, your device type, browser, screen size, language and time zone. Your IP address is turned into a code that changes every day; it is never stored as it is.
Why
To see how long lessons are read and where readers leave. Not shared with anyone.
Stored
A random visitor ID, a visit ID and the time of your last page view in your browser’s storage (gr_vid, gr_sid, gr_last). No name or email is attached.