git diff --no-index: Diff Files Outside a Repo
git diff --no-index compares any two paths with Git's diff engine, whether or not they are tracked or even inside a repository.
This gives you Git's coloring, word-diff, and rename detection for files that have nothing to do with a repo, and it produces a proper unified diff you can apply with git apply.
What it does
git diff --no-index <a> <b> treats the two paths as plain files or directories and diffs them, bypassing the index entirely. The output is a standard git-style unified diff. Crucially for CI, it exits 1 when the inputs differ and 0 when they match, the same as adding --exit-code.
Common usage
git diff --no-index expected.json actual.json
# whole directories
git diff --no-index dist/ expected-dist/
# word-level diff of two docs
git diff --no-index --word-diff a.md b.mdOptions
| Flag | What it does |
|---|---|
| --no-index | Diff the two paths without using the repo index |
| --word-diff | Show intra-line word-level changes |
| --stat | Summarize with a diffstat-style histogram |
| --color=always | Force color in non-TTY CI logs |
| exit 1 | The inputs differ (implicit with --no-index) |
In CI
git diff --no-index is a great staleness gate when Git is already installed but the files are not tracked: git diff --no-index committed generated fails the step on any difference and prints an applyable patch. Add --color=always to keep the diff readable in the CI log.
Common errors in CI
People are surprised that the step "fails" with exit 1: that is by design, --no-index behaves like --exit-code. "fatal: <path>: no such path in the working tree" or "usage: git diff --no-index" means you gave one path or the paths do not exist. Unlike a tracked git diff, --no-index ignores .gitignore, so build artifacts are compared too.