Skip to main content

Undo Mistakes

Git's safety net is larger than most people realize. Almost every "mistake" is recoverable. This lesson covers the full toolkit for undoing changes at every stage.


Stash: Save Work in Progress

You are mid-way through a change and need to switch branches urgently — but you are not ready to commit. git stash saves your uncommitted changes and restores a clean working directory.

# Save your WIP
git stash

# Your working directory is now clean
git status # nothing to commit

# Do the urgent thing (switch branches, pull, etc.)
git switch main
git pull

# Come back to your WIP
git switch -
git stash pop # restore your stashed changes

Stash with a description

git stash push -m "half-finished refactor of login form"

See all stashes

git stash list
stash@{0}: On feature-x: half-finished refactor of login form
stash@{1}: WIP on main: fix typo

Restore a specific stash

git stash pop stash@{1}

Discard Unstaged Changes

Changed a file and want to throw the changes away and go back to the last committed version:

git restore <file>

This is destructive — the unsaved changes are gone. There is no undo.

Discard all unstaged changes in the project

git restore .

Unstage a File

You ran git add but changed your mind about including a file in the next commit:

git restore --staged <file>

This moves the file back from the Staging Area to the Working Directory. Your changes are preserved — they are just no longer staged.


Undo a Commit (Soft Reset)

You just committed something and want to uncommit it, but keep the changes staged:

git reset --soft HEAD~1

HEAD~1 means "one commit before HEAD." The commit is gone from history, but all the changes are still in the Staging Area, ready to be recommitted differently.

Use this when you want to redo a commit with a different message or a different set of files.


Undo a Commit (Hard Reset)

Destructive

git reset --hard permanently deletes commits and their changes. Only use this for local, unpushed work you are certain you want to discard.

git reset --hard HEAD~1

The last commit is removed from history and its changes are deleted from your working directory entirely.


Safe Undo for Pushed Commits

If a commit is already on GitHub and others may have pulled it, do not use git reset. Use git revert instead:

git revert <commit-hash>

git revert creates a new commit that reverses the changes of the specified commit. The original commit stays in history. This is safe because it does not rewrite history — it only adds to it.

git reset (rewrites history):ABCdeletedgit revert (adds to history):ABCC'undoes C

The Ultimate Safety Net: Reflog

git reflog records every state HEAD has been in, including commits you "deleted" with git reset.

git reflog
a1b2c3d HEAD@{0}: reset: moving to HEAD~1
9f8e7c6 HEAD@{1}: commit: The commit you "lost"
3d2c1b0 HEAD@{2}: commit: Previous commit

To recover a "lost" commit, reset back to it:

git reset --hard 9f8e7c6

Reflog entries expire after 90 days by default. For practically all real-world accidents, your work is still there.


Which Command to Use

SituationCommand
Undo staged files (keep changes)git restore --staged <file>
Discard unstaged changesgit restore <file>
Save WIP without committinggit stash / git stash pop
Undo last commit (keep staged)git reset --soft HEAD~1
Undo last commit (discard changes)git reset --hard HEAD~1
Undo a pushed commit safelygit revert <hash>
Recover "lost" workgit reflog then git reset --hard <hash>
Donate to this project