Discard local changes and get back to a clean state
How do I throw away all my local changes in Git?
Short answer
git restore . discards edits to tracked files and git clean -fd deletes untracked ones. Both are irreversible for anything that was never staged or committed, so run git stash first if there's any doubt — it takes a second and makes the whole operation undoable.
git stash -u
# verify you really don't need it, then:
git stash drop
The reversible way to get a clean tree — stash first, delete later
Does this match your situation?
- You experimented, it didn't work, and you want the state of the last commit back.
- git status shows a mess of modified and untracked files.
- You need a clean tree before switching branches or pulling.
Step-by-step fix
Stash instead of deleting — the reversible route
This gets you a pristine working tree just like discarding does, but everything is recoverable. If you find in ten minutes that you needed one of those files, it's still there.
step 1git stash push -u -m "experiment I probably do not need"-u includes untracked files, which plain git stash leaves behind.
Discard changes to tracked files
This overwrites your edited files with the versions from the last commit. There is no confirmation prompt and no undo — the content was never in Git, so nothing can retrieve it.
step 2git restore . # everything under this directory git restore src/app.ts # one file # classic equivalent: git checkout -- .Preview untracked files before deleting them
git clean deletes files Git isn't tracking. Always run the dry run first — the -x flag in particular will remove ignored files like .env and local configuration you may not have anywhere else.
step 3git clean -nd # dry run: list what WOULD be deleted git clean -fd # delete untracked files and folders git clean -fdx # also delete IGNORED files — including .env-x is the flag that catches people out. It deletes your .env, local settings and anything else .gitignore covers.
Reset the whole tree to the last commit
To wipe both tracked modifications and staged changes in one step, reset hard to HEAD. Combine it with clean if you also want untracked files gone.
step 4git reset --hard HEAD git clean -fd
Why this works
Everything Git can restore, it restores from the object database. Your uncommitted edits were never written there — they exist only as bytes on your disk — so overwriting them removes the only copy in existence. This is the one category of loss the reflog and fsck cannot help with, and it's why 'stash instead of discard' is such a valuable habit: stashing writes the content into the object database first, which converts an irreversible delete into a reversible one.
How to stop it happening again
- Make git stash -u your reflex instead of git checkout -- . or git clean.
- Always run git clean -nd before git clean -fd, every single time.
- Commit experiments to a scratch branch — you can always delete the branch later.
Commands used in this guide
git restoreThrow away working-directory changes or unstage files (the modern, clearer replacement for checkout).
git cleanDelete untracked files and directories from your working tree.
git stashPark uncommitted work temporarily so you can do something else.
git resetMove the current branch pointer, optionally rewriting the index and your files.
Still stuck?
Search the full command reference and every other rescue guide — there are 56 of them, covering everything from detached HEAD to force-push disasters.
Browse all guides →Frequently asked questions
How do I discard all local changes in Git?
git restore . discards modifications to tracked files, and git clean -fd removes untracked files and directories. To also clear staged changes, use git reset --hard HEAD first. All of these are irreversible for uncommitted content.
Can I undo git checkout -- . or git restore?
Generally no. Those commands overwrite working-directory files whose content was never stored in Git, so there's nothing to recover from. The exceptions are if the file had been staged at some point (git fsck may find a dangling blob) or if your editor's local history has a copy.
What does git clean -fdx actually delete?
-f forces the deletion, -d includes untracked directories, and -x also removes files that .gitignore excludes. That last flag is the dangerous one: it deletes .env files, local configuration and build caches that may not exist anywhere else. Always dry-run with -nd or -ndx first.
Related rescue guides
How do I undo git add without losing my changes?
git restore --staged <file> removes a file from the staging area and leaves your edits completely untouched. The older equivalent is git reset HEAD <file>. Neither one touches the contents of your file, so this is a zero-risk operation.
Read the fix →Sometimes recoverableI permanently deleted a file that was never committed — can I get it back?
It comes down to one question: was the file ever staged with git add? If it was, its contents are sitting in Git's object database as a dangling blob and git fsck will find it. If it was never staged and never committed, Git genuinely never saw the file and cannot help — but your editor's local history almost certainly can.
Read the fix →Usually recoverableI ran git stash drop (or git stash clear) — can I get the stash back?
Stashes are stored as real commit objects, so dropping one only removes it from the stash list — the commit itself survives as an unreachable object. git fsck --unreachable finds it, and git stash apply <hash> puts the work back.
Read the fix →Usually recoverableI ran git reset --hard and lost my commits — how do I undo it?
Committed work is almost never really gone. git reflog lists every position HEAD has held, including the one just before your reset, so you can jump straight back to it with git reset --hard HEAD@{1}. Uncommitted changes that the reset wiped are a different story — those are only recoverable if they had been staged at some point.
Read the fix →