On This Page

How to Undo the Last Commit in Git

Quick Summary: To undo your last local commit while keeping all your code modifications staged, run git reset --soft HEAD~1. To unstage your changes while preserving your edited files in your workspace, run git reset HEAD~1. To completely discard the last commit and throw away all uncommitted changes, run git reset --hard HEAD~1.


Quick Reference Cheat Sheet

GoalCommandWhat happens to your code?
Keep changes stagedgit reset --soft HEAD~1Commit undone. All changed files remain staged in index.
Keep changes in workspacegit reset HEAD~1Commit undone. Changes stay in files but become unstaged.
Discard changes completelygit reset --hard HEAD~1Commit undone. All modifications in the commit are deleted.
Change last commit messagegit commit --amend -m "New message"Replaces last commit with updated message without resetting.
Undo commit already pushedgit revert HEADCreates a new reverse commit without rewriting remote history.

Scenario 1: Undo Commit but Keep Changes Staged (--soft)

Use this when you committed too early, forgot a file, or want to combine multiple commits before pushing.

$ git reset --soft HEAD~1

What happens under the hood?

  1. Git rewinds your active branch pointer (e.g. .git/refs/heads/main) back by 1 commit.
  2. The Staging Area (.git/index) is not modified — all files from the undone commit remain staged.
  3. Your Working Directory files remain untouched.

You can now add missing files and run git commit again.


Scenario 2: Undo Commit & Unstage Changes (--mixed / Default)

Use this when you want to unstage everything and re-examine your changes file-by-file.

$ git reset HEAD~1
# (or git reset --mixed HEAD~1)

What happens under the hood?

  1. Git rewinds your active branch pointer back by 1 commit.
  2. The Staging Area is updated to match the previous commit (un-staging all changes).
  3. Your Working Directory files are preserved with your local edits intact.

Scenario 3: Delete Commit & Discard All Changes (--hard)

Use this when you made a mistake and want to permanently erase the last commit and all associated file edits.

⚠️ Warning: This destroys uncommitted local modifications. Double check before running!

$ git reset --hard HEAD~1

What happens under the hood?

  1. Git rewinds your active branch pointer back by 1 commit.
  2. The Staging Area is reset to match the previous commit.
  3. Your Working Directory files are overwritten to match the previous commit.

Scenario 4: Just Fix the Commit Message (--amend)

If you just made a typo in your commit message, you don’t need to reset the commit. Use --amend instead:

$ git commit --amend -m "Corrected commit message"

If you forgot to include a file:

$ git add forgotten-file.js
$ git commit --amend --no-edit

Scenario 5: Undo a Commit Already Pushed to GitHub / Remote (git revert)

If you have already run git push, resetting your local history with git reset will cause conflicts with your remote branch. Instead of rewriting history, create a new commit that undoes the previous one using git revert:

$ git revert HEAD
$ git push origin main

git revert leaves your commit history transparent while safely backing out the changes.


Emergency Recovery: “I ran git reset --hard by accident!”

If you accidentally ran git reset --hard and lost a commit, don’t panic! Git rarely deletes objects immediately. You can recover lost commits using git reflog:

# 1. List all recent reference updates
$ git reflog

# Output example:
# e4f2a1b HEAD@{0}: reset: moving to HEAD~1
# a9b8c7d HEAD@{1}: commit: Add new user authentication feature

# 2. Restore your repository to the hash before the reset
$ git reset --hard HEAD@{1}

Frequently Asked Questions

What does HEAD~1 mean?

HEAD points to your current commit. HEAD~1 means “one commit before HEAD” (the immediate parent commit). HEAD~2 refers to two commits back.

Is git reset safe to use on public branches?

Local resets are safe as long as you haven’t pushed the commits to a shared repository. If other developers have pulled your commits, use git revert instead.