Undo a changeRarely recoverable by Git

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.

quick fix
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

  1. 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 1
    git stash push -u -m "experiment I probably do not need"
    

    -u includes untracked files, which plain git stash leaves behind.

  2. 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 2
    git restore .                 # everything under this directory
    git restore src/app.ts        # one file
    
    # classic equivalent:
    git checkout -- .
    
  3. 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 3
    git 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.

  4. 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 4
    git 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 restore

Throw away working-directory changes or unstage files (the modern, clearer replacement for checkout).

git clean

Delete untracked files and directories from your working tree.

git stash

Park uncommitted work temporarily so you can do something else.

git reset

Move 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

Always fixable

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 recoverable

I 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 recoverable

I 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 recoverable

I 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 →
← All Git Rescue guides