Home / Alt manpages / git-clean(1)

  • git-clean(1)
  • User command
  • linux

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.

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:

  • -x ignores the repository's normal ignore rules and includes ignored files, while still applying any command-line -e exclusions. This is the broadest cleanup mode.
  • -X removes only files ignored by Git. It keeps untracked files that you created manually.
  • -e PATTERN adds 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 -n or git clean -nd candidate 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 --short and a filesystem check show the intended result.