How to remove untracked files from a Git working tree
git clean removes files git is not
tracking. It is the right tool, and it is also one of the two or three git
commands that can genuinely lose work, so it is worth being deliberate about.
Look before you delete
$ git clean -nd
Would remove build/
Would remove untracked.txt
-n is a dry run — it prints and deletes nothing. Make this the reflex. There
is no undo for the real thing, so the two seconds are well spent.
Then do it
$ git clean -fd
files after : .gitignore ignored.log tracked.txt
-f is required because git refuses without it:
fatal: clean.requireForce is true and -f not given: refusing to clean
-d includes directories. Without it, build/ would have been left alone —
clean works on files by default and a directory containing only untracked
files is skipped.
-x is a bigger deal than it looks
Note what survived above: ignored.log. Files matched by .gitignore are not
touched by a plain git clean.
$ git clean -fdx
files after : .gitignore tracked.txt
-x removes ignored files too. In a real repository that means .env,
node_modules/, vendor/, build caches, editor state — everything you
deliberately kept out of the repository, including the things that are annoying
or impossible to reconstruct.
-fdx is genuinely useful for “give me a pristine checkout”, which is why CI
uses it. On your own machine, run -ndx first and read the list.
It only deals with untracked files
An easy assumption is that clean gives you a pristine tree. It does not:
tracked.txt after clean : keep modified
tracked.txt after restore : keep
A tracked file you have modified is not untracked, so clean ignores it
completely. Removing your changes there is a different command:
$ git restore . # discard changes to tracked files
$ git clean -fd # remove untracked files
The two halves together are what “reset everything” actually means. Neither does the other’s job.
There is nothing to recover
Every other undo in this series has a safety net.
git reflog finds commits after a
reset --hard; a force-deleted branch is still reachable by hash.
Untracked files have none of that, and the reason is structural rather than a missing feature: they were never added to the index and never committed, so nothing about them ever entered git’s object database. There is no old version to go back to, because git never had one.
If you are unsure, git stash --include-untracked parks them somewhere
recoverable instead. And git clean -i steps through interactively, which is
the sensible choice on a repository you do not know well.
About Netcup (advertisement)
The German host Netcup offers, among other things, affordable and powerful web hosting packages, KVM-based root servers and dedicated servers. With our voucher codes you can save even more (6€ off your first order, 30% off all KVM-based root servers, ...).