git diff --name-only and --diff-filter: Changed Files in CI
git diff --name-only <base> HEAD lists just the changed file paths, the basis of path-filtered CI (only run a job when its directory changed); --diff-filter narrows by change type.
Monorepo pipelines decide what to build from the set of changed files. --name-only gives that set, --name-status labels each change, and --diff-filter lets you act only on, say, added or deleted files.
What it does
git diff --name-only prints the paths that differ between two tree-ishes. --name-status prefixes each with its status letter (A added, M modified, D deleted, R renamed). --diff-filter=<letters> restricts to those change types. -z NUL-delimits the output for safe scripting. The three-dot form base...HEAD diffs against the merge base.
Common usage
# files changed between the PR base and HEAD
git diff --name-only origin/main...HEAD
# only added or modified files, NUL-safe
git diff --name-only --diff-filter=AM -z origin/main...HEAD
# with status letters
git diff --name-status origin/main...HEAD
# staged changes only
git diff --cached --name-onlyOptions
| Flag | What it does |
|---|---|
| --name-only | List changed paths only |
| --name-status | List paths prefixed with the change status |
| --diff-filter=<ACDMR...> | Select changes by type (e.g. AM = added/modified) |
| -z | NUL-delimit output for safe parsing |
| --cached / --staged | Diff the index against HEAD |
| <base>...<head> | Diff against the merge base (three dots) |
In CI
Use base...HEAD (three dots) for PR diffs so you compare against the merge base, not the moving tip of the base branch. That merge base must exist locally, so a shallow clone breaks the diff: use fetch-depth: 0 or deepen. --diff-filter=AM is handy to lint or scan only files that still exist (skipping deletions).
Common errors in CI
"fatal: ambiguous argument 'origin/main...HEAD': unknown revision" means the base ref or merge base is missing (shallow clone, ref not fetched). An empty list when you expected changes often means you diffed against the wrong base (the tip instead of the merge base). "bad revision" means a ref name does not resolve.