CommandGit

Discard all uncommitted changes

Wipes every uncommitted edit, staged or not, and removes untracked files too, resetting the working tree back to exactly the last commit.

Last updated

Commandgit
git reset --hard && git clean -fd

How it works

git reset --hard (against the implicit HEAD) throws away every staged and unstaged modification to files git already tracks, snapping them back to match the last commit exactly. It only knows about TRACKED files though, so git clean -fd runs right after to remove untracked files (-f, force — clean refuses to run without it) and untracked directories (-d) that reset --hard never touches.

Together these two commands are the standard "start completely over from the last commit" combo — reset handles what git is already tracking, clean handles everything else sitting in the working tree that git doesn't know about yet.

Watch out for

  • →This is destructive and permanent from git's point of view — there is no undo command for git clean the way there sometimes is for a bad reset via the reflog; anything it removes is genuinely gone.
  • →git clean -fd does NOT remove files matched by .gitignore by default (build output, node_modules, etc.) — add -x to also wipe ignored files, or run git clean -fdn first (dry run) to see exactly what would be deleted before committing to it.
  • →Run this only when you're certain nothing in the working tree is worth keeping — if you're unsure, git stash first so the changes are recoverable instead of permanently discarded.

Part by part

git reset --hard
Discards every tracked change, staged or not, returning tracked files to their committed state. This is irreversible.
git clean -fd
Removes untracked files and directories, which reset does not touch. The two together are what make the working tree genuinely clean.
-f
Force. git clean refuses to run without it, deliberately, because there is no undo.

Common mistakes

  • git clean -fdx

    The x also removes ignored files, which usually means node_modules, build output, and your .env with its local credentials. It turns a five-second cleanup into a reinstall and a scramble for secrets.

  • git reset --hard

    On its own it leaves untracked files behind, so a build that fails because of a stray generated file still fails afterwards. That is often why the reset appeared not to work.

    git reset --hard && git clean -fd
  • git checkout .

    Reverts tracked files in the working tree but leaves the index alone, so anything already staged survives. It looks like it did the job right up until you commit.

Questions

Can I preview what clean will delete?

Yes, and you should: git clean -nd lists the files without removing any. It costs a second and it is the only chance you get, since nothing here goes to a trash folder.

Is there any way back after this?

For committed work, yes via reflog. For uncommitted changes, no — they were never in git's object store, so there is nothing to recover. This is the command to be sure about before running.

How do I keep the changes instead of destroying them?

git stash push -u puts everything, untracked files included, somewhere retrievable and leaves the tree clean. It gives the same result and lets you change your mind afterwards.

Why does clean need -f at all?

Because git treats deleting untracked files as dangerous enough to require an explicit confirmation. You can remove the requirement with the clean.requireForce setting, which is worth not doing.

Related in Commands