Safely Remove Untracked Files with git clean
You will finish with a repeatable way to remove disposable files from a Git working tree without guessing what the command will delete. The examples use Git 2.43.0, matching the installed git-clean(1) manual on this machine. Allow about ten minutes, plus time to inspect the dry-run list carefully.
The route
Jump straight to the step you need, or tick off Done means at the end.
This is an ordinary user command. It does not need sudo when the repository and its files belong to you. It is destructive: git clean removes files from the working tree, and those files are not recoverable from Git because Git does not track them. Keep anything you may need before continuing.
1. Check the repository before cleaning
Change to the repository you intend to clean, then inspect its state. This step changes nothing:
$ cd /path/to/repository
$ git --version
git version 2.43.0
$ git status --short
Read the status output before using any removal option. Entries beginning with ?? are untracked. Modified or staged tracked files are not what git clean targets, but do not confuse a clean working tree with a safe deletion list. An untracked directory may contain several files that status condenses to one line.
Checkpoint: you know the repository path, the installed Git version, and which untracked files are disposable.
2. Preview ordinary untracked files
Start with a dry run. The -n option prints what would be removed and does not remove anything:
$ git clean -n
Would remove .cache-marker
Your names will differ. By default, ignored files are left alone, and untracked directories are not entered when no pathspec is supplied. This conservative default is why a plain dry run can show a file but omit a directory containing other disposable files.
Do not add -f until every line in the dry-run output is understood. If the output includes a file that you need, stop and adjust the scope or add an exclusion.
3. Include untracked directories deliberately
Add -d when you want the command to recurse into untracked directories:
$ git clean -nd
Would remove .cache-marker
Would remove build/
Would remove scratch/
Here -n still means preview; -d only broadens the candidates. A supplied pathspec makes -d irrelevant: files matching that pathspec are considered, including files below a directory. Prefer a narrow pathspec when you already know the disposable area:
$ git clean -nd -- build/
Would remove build/
The trailing -- separates options from paths. It is useful when a path begins with a dash or when you want the command shape to be obvious in a script.
4. Decide how ignored files should be treated
Build products are often ignored, so they do not appear in the normal dry run. Choose one of these modes and preview it first:
-xignores the repository's normal ignore rules and includes ignored files, while still applying any command-line-eexclusions. This is the broadest cleanup mode.-Xremoves only files ignored by Git. It keeps untracked files that you created manually.-e PATTERNadds an exclusion pattern for this invocation. For example,git clean -ndx -e '*.local'previews an ignored-inclusive cleanup while retaining matching local files.
$ git clean -ndx
Would remove build/
Would remove .env.local
$ git clean -ndX
Would remove build/
Would remove .env.local
The exact lists depend on .gitignore and your global excludes. Treat -x as a high-risk option: it can include generated credentials, local configuration and downloaded data. Inspect the list rather than assuming that "ignored" means "safe to lose".
5. Perform a reviewed cleanup
Once the matching dry run is correct, add -f. Git requires force or interactive mode by default because deletion is irreversible:
$ git clean -fd -- build/
Removing build/
$ git status --short
Use the same scope, ignored-file mode and pathspec that you reviewed. For example, a reviewed cleanup of ignored build output might be git clean -fdx -- build/. Do not turn a successful dry run into a wider command by dropping the pathspec or adding -x at the last moment.
A nested untracked Git repository is an extra boundary. Git refuses to modify one unless you pass a second -f, such as git clean -ffdx -- vendor-copy/. That command can destroy an entire nested repository. Use it only after checking the nested directory separately; there is no Git undo for the files it removes.
6. Use interactive mode for a mixed directory
When the candidate list contains both disposable and useful files, use -i instead of forcing a broad deletion:
$ git clean -i -d
Would remove the following items:
build/
notes.txt
*** Commands ***
1: clean 2: filter by pattern
3: select by numbers 4: ask each
5: quit 6: help
What now>
Choose 3 to select particular numbered entries, 4 to confirm items one by one, or 5 to leave without cleaning. Interactive mode shows a candidate list, but still leads to deletion when you confirm it. Quit if the list is surprising.
7. Verify the result and recover sensibly
After cleaning, check both the status and the filesystem:
$ git status --short
$ test ! -e build/ && echo 'build directory removed'
build directory removed
Tracked files and their history are unaffected. Untracked files removed by git clean cannot be restored with git restore or git reset; those commands operate on Git-known content. Recovery requires an independent copy, filesystem snapshot or undelete tool, and success is not guaranteed. If you have not yet run the force command, recovery is simply to quit and rerun the dry run with a narrower pathspec or an exclusion.
Done means
- You checked the repository and Git version before changing anything.
- You reviewed the exact
git clean -norgit clean -ndcandidate list. - You chose ordinary, ignored-only or ignored-inclusive cleanup deliberately.
- You used a pathspec or exclusion where a whole-repository cleanup was unnecessary.
- You understand that
-f, especially repeated-f, permanently removes untracked data. git status --shortand a filesystem check show the intended result.