# git clean -fdx vs -fdX: Removing Untracked Files

> git clean removes untracked files; -x clears ignored files too while -X removes only ignored ones. Reference for -f, -d, -n, and the safe CI patterns.

Source: https://latchkey.dev/learn/command-reference/git-clean-modes  
Updated: 2026-06-30

git clean -fd removes untracked files and directories; adding -x also removes ignored files (build output), while -X removes only the ignored ones, leaving new source untouched.

Resetting a runner workspace means deleting untracked junk, but the difference between lowercase -x and uppercase -X decides whether you wipe build caches or only them. Always dry-run with -n first.

## What it does

git clean deletes untracked files. -f is required to actually delete (force). -d also recurses into untracked directories. -x removes files that .gitignore would normally protect (node_modules, dist), giving a pristine tree. -X removes only ignored files and keeps untracked, not-yet-added source. -n shows what would be deleted without deleting.

## Common usage

```Terminal
git clean -n -d                 # dry run: list what would go
git clean -fd                   # remove untracked files + dirs
git clean -fdx                  # also remove ignored (full reset)
git clean -fdX                  # remove ONLY ignored files
# combine with hard reset for a pristine workspace
git reset --hard && git clean -fdx
```

## Options

| Flag | What it does |
| --- | --- |
| -f / --force | Actually delete (required unless clean.requireForce=false) |
| -d | Recurse into untracked directories |
| -x | Also remove ignored files (use the full ignore set) |
| -X | Remove ONLY ignored files, keep other untracked files |
| -n / --dry-run | List what would be removed without removing |
| -e <pattern> | Add an exclude pattern on top of .gitignore |

## In CI

On persistent or self-hosted runners, git clean -fdx between jobs prevents stale artifacts from leaking into a build, but it also blows away caches, so weigh -fdx (full reset) against -fdX (drop only ignored build output). git reset --hard does not touch untracked files; pair it with git clean to truly reset. Dry-run with -n in a new pipeline before trusting -f.

## Common errors in CI

"fatal: clean.requireForce defaults to true and neither -i, -n, nor -f given" means you forgot -f. "Cowardly refusing to clean the current working directory" can appear in edge cases; run from the repo root. Surprise deletion of needed files usually means -x was used where -X (ignored only) was intended.

## Using this in CI

CI checkouts are shallow and detached by default, which changes the answer this command gives you. Commands that read history, branch names, or tags need the checkout configured for it.

```.github/workflows/ci.yml
- uses: actions/checkout@v4
  with:
    fetch-depth: 0   # history, tags, and git describe all need this

- run: |
    git rev-parse --is-shallow-repository   # expect false
    git rev-parse --abbrev-ref HEAD          # prints HEAD when detached
```

> `git rev-parse --abbrev-ref HEAD` returns the literal string `HEAD` on a detached checkout rather than a branch name. On GitHub Actions read `github.ref_name` instead; the git command cannot know what it was checked out for.

## FAQ

### git clean -fdx vs -fdX: Removing Untracked Files?

Resetting a runner workspace means deleting untracked junk, but the difference between lowercase -x and uppercase -X decides whether you wipe build caches or only them. Always dry-run with -n first.

### What it does?

git clean deletes untracked files. -f is required to actually delete (force). -d also recurses into untracked directories. -x removes files that .gitignore would normally protect (node_modules, dist), giving a pristine tree. -X removes only ignored files and keeps untracked, not-yet-added source.

### In CI?

On persistent or self-hosted runners, git clean -fdx between jobs prevents stale artifacts from leaking into a build, but it also blows away caches, so weigh -fdx (full reset) against -fdX (drop only ignored build output). git reset --hard does not touch untracked files; pair it with git clean to truly reset.

### Common errors in CI?

"fatal: clean.requireForce defaults to true and neither -i, -n, nor -f given" means you forgot -f. "Cowardly refusing to clean the current working directory" can appear in edge cases; run from the repo root. Surprise deletion of needed files usually means -x was used where -X (ignored only) was intended.

---

Latchkey runs CI/CD that repairs its own failures. Agent entry points: https://latchkey.dev/agent.txt, https://latchkey.dev/openapi.json, https://latchkey.dev/llms.txt
