Introduction
Your working directory has accumulated debris: node_modules you never committed, build artifacts, log files, editor configs that slipped through gitignore. You know they're not tracked by Git, but they're cluttering your workspace and making it harder to see what actually changed. This is where git clean: what every Git & GitHub developer should know becomes essential. Learning to safely remove untracked files is a skill that separates developers who manually delete files one by one from those who clean up efficiently and confidently.
We'll walk through the flags that matter, the preview workflows that keep you safe, and the gotchas that catch even experienced developers.
Understanding what git clean does
The git clean command removes files that Git doesn't track. Unlike git reset or git checkout, which operate on the staging area or committed history, git clean targets only untracked content. This is powerful but also dangerous, because untracked files don't have a safety net—once deleted, they're gone unless you have backups.
By default, git clean does nothing. You need flags to make it actually delete anything. Git takes this conservative stance intentionally. Running git clean with no flags shows you what would be removed, but it won't remove anything. This is a deliberate friction point to prevent accidents.
Previewing with git clean -n
Before deleting anything, you need visibility. The -n flag (short for --dry-run) shows you what git clean would remove without actually removing it. This is your safety valve and should be your first step every time.
git clean -nRunning this in a typical Node.js project might output:
Would remove node_modules/
Would remove dist/
Would remove .env.local
Would remove test-results.jsonThis preview is non-destructive. Run it, inspect the output, and make sure nothing you care about appears in the list. Real-world scenario: you've been working on a feature branch, ran npm install multiple times, and now you have node_modules, generated TypeScript files in dist/, and some test artifacts. Before running the actual clean, preview what's there. If the list looks right, proceed. If you see something unexpected—maybe a file you were working on but forgot to stage—stop and investigate.
The pattern we follow on teams is simple: always run -n first, read the output carefully, then run the actual command if the preview matches your expectations.
Deleting files and directories with git clean -fd
Once you're confident in the preview, use -f to force deletion and -d to remove directories. The -f flag is required as another safety layer; Git won't delete untracked files without it. The -d flag tells Git to also remove empty directories.
git clean -fdThis combination is the most common command you'll use in practice. It removes all untracked files and the directories that contained them. In a production scenario, you might do this before deploying from a CI/CD pipeline or before switching to a critical branch where you want a completely clean state.
Example: you've been debugging a complex issue and created several temporary test files, debug logs, and a scratch directory. You didn't commit any of these (they're all in .gitignore or just never staged). Run:
git clean -nSee the files and folders listed. Confirm they're all expendable. Then:
git clean -fdThe files vanish. Your working directory is clean. Now you can switch branches or start fresh with confidence.
One nuance: -d removes only directories that become empty after files are deleted. It doesn't remove directories that already had content you wanted to keep. This is safer than it sounds, but it's still worth understanding the scope of what you're deleting.
Removing ignored files with git clean -x
By default, git clean respects your .gitignore file—it won't touch files that are ignored. This is usually correct behavior. Ignored files like node_modules, build outputs, and environment files often aren't truly "junk"; they're build artifacts or secrets you explicitly don't want to commit.
Sometimes, though, you need to remove everything, including ignored files. Add the -x flag:
git clean -xnPreview what would be removed. Then:
git clean -xfdNow git clean removes both untracked files and ignored files. Be extremely careful with this command. In a Node.js project, it will delete node_modules, dist, build artifacts, .env files, and logs—everything that's not committed. You're back to a freshly cloned repo state.
Real-world use case: you're preparing for a clean build in CI/CD. Your deployment script might run git clean -xfd to ensure no stale artifacts from previous runs interfere with the current build. Or you're switching to a branch with a completely different project structure, and you want to guarantee no old build outputs are left behind.
A safer variant is -X (capital X), which removes only ignored files, leaving untracked files alone:
git clean -XfdThis is useful when you want to purge build artifacts and secrets without touching untracked files you might still be working on.
Interactive cleaning with git clean -i
If you're unsure which files to delete and want fine-grained control, use the interactive flag:
git clean -idGit presents a menu where you can select which files and directories to delete. This takes longer than a dry run followed by the actual command, but it's useful when you have a complex working directory and want to be selective.
The flow: Git lists untracked files, you choose which ones to remove, and it confirms before deleting. It's slower than -n then -fd, but the safety and clarity can be worth it on unfamiliar codebases or when you're new to a project.
Common mistakes
Running git clean -fd without -n first: This is the biggest risk. You skip the preview, assume everything is safe, and accidentally delete a file you were working on. Always preview.
Using -x or -X carelessly: These flags remove ignored files, including dependencies and configuration. On a team, different members might have different .gitignore files or local config. Preview with -xn or -Xn first.
Forgetting you need -f: Running git clean -d without -f won't delete anything. You might assume the command succeeded when nothing happened. Always include -f unless you're using interactive mode.
Confusing git clean with git reset: git reset operates on staged changes and committed history. git clean removes untracked files. They solve different problems. Don't mix them up.
Using git clean in a shared repository without checking .gitignore: If your .gitignore differs from teammates' versions, git clean -x might delete files they depend on. Standardize .gitignore first or communicate clearly.
Workflow recommendations
Here's the safe workflow we follow:
- Run
git statusto see the overall state of your repository. - Run
git clean -nto preview what would be removed. - Review the output carefully. If anything looks wrong, stop.
- Decide whether you need
-d(directories),-x(ignored files), or both. - Run the actual command with the appropriate flags.
- Run
git statusagain to confirm.
On CI/CD pipelines, we often add this to deployment scripts:
git clean -xfd --exclude=.env.productionThe --exclude flag lets you protect specific files even when using -x. Useful for secrets or configuration you want to preserve during a clean.
Key takeaways
- Always run
git clean -nbefore running the actual command to preview what will be deleted. git clean -fdremoves untracked files and empty directories; use this for typical cleanups.-xalso removes ignored files (node_modules, build artifacts, etc.); preview with-xnfirst.-fis required to actually delete anything; without it, nothing happens.- Integrate
git cleaninto deployment and CI/CD workflows to guarantee consistent build environments. - Use
--excludeto protect specific files when running aggressive cleans. - Communicate with your team about .gitignore standards so everyone's cleanup expectations align.






Comments
Loading comments…