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, ...).