Mistakes happen. You delete the wrong code, make changes that break everything, or realize you have been working on the wrong approach. The good news: Git has your back. The bad news: Git gives you multiple ways to undo things, and choosing the wrong one can make things worse.
This lesson covers how to discard local changes, unstage files, and reset your working directory, but more importantly, it helps you understand which tool to use when, so you do not accidentally delete work you wanted to keep.
Understanding change states
Before you can undo something, you need to understand where it is:
| State | Location | Description |
|---|---|---|
| Committed | Repository | Saved permanently in Git history |
| Staged | Staging area | Added with git add, ready to commit |
| Modified | Working directory | Changed but not staged |
Your undo strategy depends entirely on which state your changes are in.
Discarding local changes (modified files)
You have edited a file but have not staged it yet. Now you want to throw those changes away:
# Restore a single file
git restore filename.txt
# Restore all files in the current directory
git restore .git checkout -- file to discard changes. That is the legacy syntax and still works, but git restore is the modern, clearer command. More importantly, AI rarely warns you that this is destructive and permanent. Always run git diff first to see what you will lose.Unstaging files
You ran git add on a file but changed your mind:
# Unstage a single file (changes stay in working directory)
git restore --staged filename.txt
# Unstage all files
git restore --staged .If you want to both unstage AND discard:
git restore --staged filename.txt # Step 1: Unstage
git restore filename.txt # Step 2: Discard changesModern vs legacy syntax
| Modern | Legacy | What it does |
|---|---|---|
git restore file | git checkout -- file | Discard local changes |
git restore --staged file | git reset HEAD file | Unstage file |
The legacy commands work fine, but git restore is more explicit about what it is doing.
Nuclear option: reset --hard
Sometimes you just want to start over completely:
git reset --hard HEADThis resets the staging areaWhat is staging area?A holding zone in Git where you place changes you want to include in your next commit, letting you select exactly which modifications to save. and working directory to match the last commitWhat is commit?A permanent snapshot of your staged changes saved in Git's history, identified by a unique hash and accompanied by a message describing what changed.. All uncommitted changes, staged and unstaged, are gone permanently.
git reset --hard without mentioning safer alternatives. This command permanently deletes all uncommitted work with no recovery option. Before using it, consider git stash instead, which saves your changes for later.The safer alternative: git stash
Before you discard anything, consider stashing instead. Stashing saves your changes without committing them:
# Save all changes to the stash
git stash
# See your stashes
git stash list
# stash@{0}: WIP on main: a1b2c3d Add user authentication
# Get your changes back
git stash pop
# Apply stash but keep it in the list
git stash applyCommon undo scenarios
"I modified a file but have not staged"
# First, see what you will lose
git diff config.js
# If you are sure, restore it
git restore config.js
# Safer alternative: stash it
git stash push config.js"I staged a file but have not committed"
# Unstage it
git restore --staged secret.txt
# Optionally discard the changes too
git restore secret.txt"I want to start over completely"
# The safe way - stash everything
git stash
# Working directory is clean, changes are saved
# The dangerous way - delete everything
git reset --hard HEAD
# Working directory is clean, changes are GONECheck before you undo
Always verify what you are about to lose:
git status # See all uncommitted changes
git diff # See unstaged changes
git diff --staged # See staged changesQuick reference
| Situation | Command | Result |
|---|---|---|
| Discard changes in a file | git restore file | File reverted to committed state |
| Discard all uncommitted changes | git restore . | All files reverted |
| Unstage a file | git restore --staged file | Changes remain, but unstaged |
| Unstage all files | git restore --staged . | All changes remain, but unstaged |
| Nuclear reset | git reset --hard HEAD | All uncommitted work deleted |
| Save changes for later | git stash | Changes saved, directory clean |
| Get stashed changes back | git stash pop | Changes restored |