Cleaning untracked files (git clean)
git clean deletes untracked files (and optionally directories) from the working tree — the one undo command that targets files Git isn’t yet versioning.
Why it matters
Build artifacts, generated code, downloaded fixtures, and stray scratch files accumulate as untracked clutter that no restore or reset will remove. git clean returns the tree to a pristine, just-cloned state — essential before a clean rebuild, when reproducing a “works on my machine” bug, or in CI to guarantee no leftover output skews the next run.
How it works
git clean operates only on untracked paths; tracked files (even modified) are never touched. Because it permanently deletes, Git refuses to run without a force flag unless clean.requireForce=false.
| Flag | Effect |
|---|---|
-n | dry run — list what would be deleted, delete nothing |
-f | force the deletion (required to actually remove) |
-d | also remove untracked directories |
-x | also remove ignored files (.gitignore no longer protects) |
-X | remove only ignored files, keep other untracked ones |
- Always
-nfirst —git clean -ndpreviews every path; only then swap to-fd. This is the single habit that prevents disasters. -xvs-X— lowercase-xignores your ignore-rules and nukesnode_modules/,target/,.env; uppercase-Xdeletes only ignored files (handy to clear build output while keeping new source). See .gitignore.- Scoping —
git clean -fd path/confines it to a subtree;-e <pattern>spares matching paths. - Pairs with git reset —hard: reset reverts tracked files, clean removes untracked ones — together they fully reset a worktree.
Example
$ git clean -nd
Would remove build/
Would remove debug.log
Would remove tmp/cache.bin
$ git clean -fd # ok, do it (directories included)
$ git clean -fdx # nuke ignored stuff too: node_modules/, .env, dist/
Pitfalls
- It is irreversible — untracked files were never in Git, so there is no reflog or stash to recover them. Skipping the
-npreview has cost people their.envand local config. -xdeletes your secrets — because it ignores.gitignore,-xhappily removes uncommitted.envand credentials; reach for-Xor-ewhen you only want build junk gone.- Forgetting
-d— without it, untracked directories are left behind and the tree isn’t actually clean. - Nested repos are spared — untracked subdirectories that contain their own
.gitneed-ffto remove; plain-fskips them by design.