Skip to content
Latchkey

diff --exit-code: Fail CI on Stale Generated Files

diff returns exit status 1 when the two inputs differ, so a plain diff can fail a CI job the moment generated output drifts from what is committed.

GNU diff has no literal --exit-code flag (that is git diff); plain diff already sets the exit code. The pattern is the same: regenerate, diff against the committed copy, let a nonzero status fail the step.

What it does

diff exits 0 when the files are identical and 1 when they differ. Because CI steps fail on any nonzero exit, running diff against a freshly generated artifact turns "the committed file is stale" into a red build. The comparable Git command, git diff --exit-code, adds an explicit flag for the same behavior.

Common usage

Terminal
# regenerate, then fail if it no longer matches what is committed
protoc --gen ... -o api.pb.new
diff -u api.pb api.pb.new  # exit 1 fails the step

# check formatting is applied (gofmt example)
diff -u <(gofmt -d .) /dev/null  # any diff output means unformatted files

Options

Flag / behaviorWhat it does
exit 0Files are identical
exit 1Files differ (fail the CI step)
exit 2Trouble: a file is missing or unreadable
-qReport only whether files differ, no per-line output
-uShow the unified diff so the failure log explains the drift

In CI

The staleness gate is: regenerate the artifact into a temp path, then diff -u committed generated. Keep -u so the job log shows exactly what changed and a developer can copy the fix. For lockfiles, run the install then diff the lockfile against HEAD. For a repo-wide check across tracked files, git diff --exit-code is usually simpler.

Common errors in CI

The confusing case is a green build that should be red: if you swallow the exit code with || true or pipe diff into another command, the failure is lost; keep diff as the last command in the step. "diff: extra operand" means you passed three paths (often an unquoted glob). Exit 2 (missing file) is not a content difference; do not treat it as "stale".

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →