Great work!

XP to next level

BugEater
EN

git clean -fd: Wiping Untracked Files Safely

Learning Objectives

By the end of this lesson you will be able to:

  • Preview a clean with -n before running it
  • Explain each of the flags -f, -d, -x and -X
  • Say why git clean is more dangerous than git reset --hard
  • Reset a test environment to a genuinely pristine state

The Gap reset --hard Leaves

git reset --hard
git status
Untracked files:
  screenshots/
  test-results/
  node_modules/
  debug.log

reset --hard restored every tracked file. Untracked ones — everything Git has never recorded — are untouched, because they are not part of any commit for Git to restore them from.

For a test environment, those leftovers are exactly what makes "it passes on my machine" happen. A stale screenshot baseline, an old report, a node_modules from a different branch's dependency set. git clean is what removes them.

Always Preview First

git clean -n -d
Would remove screenshots/
Would remove test-results/
Would remove debug.log

-n (or --dry-run) shows what would be deleted and deletes nothing. Read the list. This is not optional caution — it is the only protection you get, because what clean removes was never committed and cannot be recovered by anything.

Only when the list is what you expect:

git clean -f -d

The Flags

Flag Effect
-n Dry run — list, delete nothing
-f Force — required; without it Git refuses to delete anything
-d Include untracked directories
-x Also delete ignored files (node_modules, .env, build output)
-X Delete only ignored files, keeping other untracked ones
-i Interactive — choose what to remove, item by item

-f being mandatory is deliberate. Git will not delete untracked files on a typo.

The one to be careful with is -x. Without it, .gitignore protects your ignored files, and .env and node_modules survive. With it, they do not — and .env is not in any commit either, so it is gone for good.

git clean -f -d           # untracked files and directories, ignored ones kept
git clean -f -d -x        # everything not tracked, including .env and node_modules
git clean -f -d -X        # only ignored files — build output, keeping new source files

Why This Is More Dangerous Than reset --hard

Module 4 established the risk model: anything ever committed is recoverable; anything else is not.

git reset --hard mostly moves commits around, and the reflog gets them back. git clean deletes files that were never committed. There is no object, no reflog entry, no recovery. It is the single most permanently destructive command in this trail.

Two habits make it safe:

-n first. Always. Even when you are sure. Especially when you are sure.

-i when the list is mixed. Interactive mode walks you through the files:

git clean -i -d
Would remove the following items:
  debug.log  screenshots/  new-test-idea.spec.ts
*** Commands ***
    1: clean    2: filter by pattern    3: select by numbers
    4: ask each 5: quit                 6: help

new-test-idea.spec.ts in that list is the reason interactive mode exists. A new file you have written but not yet added is untracked, and a blanket clean -f deletes it exactly as readily as a log file.

Resetting a Test Environment

The canonical pair, and one of the most useful things in this whole trail for QA work:

git fetch origin
git reset --hard origin/main      # tracked files match the remote exactly
git clean -f -d -x                # everything else is gone

After those three commands, the working copy is identical to a fresh clone. Nothing local, nothing stale, nothing left over from the last branch you tested.

Note the -x. It removes node_modules and .env too, so you will need to reinstall dependencies and restore your local config. That is the point — dependencies from a different branch are a classic source of "works on my machine". Keep a copy of your .env somewhere outside the repository.

Pro Tip: Make alias gclean='git clean -n -d' your muscle memory, so the reflex is the preview and the destructive version requires deliberately typing something else. Several minutes of work have been lost to a -f typed on autopilot.

Key Takeaways

  • reset --hard restores tracked files; untracked files need git clean
  • git clean -n -d previews; read the list before every real run
  • -f is mandatory, -d includes directories, -x also removes ignored files, -X removes only those
  • Cleaned files were never committed, so nothing — not even the reflog — recovers them
  • -i interactive mode protects new files you have written but not yet added
  • fetch + reset --hard origin/<branch> + clean -f -d -x gives a pristine test environment
  • Keep your .env backed up outside the repository before using -x

Quiz

Why does git reset --hard leave a screenshots/ directory behind?

What does git clean -n -d do?

Which flag also removes node_modules and .env?

Why is git clean considered more dangerous than git reset --hard?