Git Diff Shows Nothing? Check the Staged Snapshot
If git diff shows nothing after git add, inspect git diff --cached. Plain git diff compares your working files with the staging area, so staging a change can make that comparison empty while the next commit still contains the change.
There is a second trap: git diff HEAD can also be empty even though a staged change remains. If you stage an edit and then manually reverse it in your editor, the working file matches HEAD, but the staging area still holds the earlier edit. A normal git commit records that staged version.
Check which two versions you are comparing
Start with these read-only commands from the repository root:
git status --shortgit diffgit diff --cachedgit diff HEADThe Git diff reference distinguishes these comparisons. --staged is a synonym for --cached.
| Command | Comparison | Question it answers |
|---|---|---|
git diff | Index → working tree | What changed since this content was staged? |
git diff --cached | HEAD → index | What tracked changes are staged for the next ordinary commit? |
git diff HEAD | HEAD → working tree | How do the current working files differ from the last commit? |
The index is Git’s staging area. It is a stored snapshot, not a live reference to your editor buffer. Pro Git’s recording-changes chapter explains why editing a file after staging creates another unstaged change.
For one file, add an exact path after --:
git diff -- settings.txtgit diff --cached -- settings.txtgit diff HEAD -- settings.txtThese commands compare snapshots; they do not list every file on disk. Check git status --short for untracked paths too.
Read the two status columns
For ordinary tracked files outside an unresolved merge, Git’s short status format uses the first column for the index and the second for the working tree:
M settings.txt M settings.txtMM settings.txt?? notes.txtThese are separate possible results, not four entries for one working copy:
M: the index differs fromHEAD; no further working-file change is reported.M: the working file differs from the index; no staged modification is reported.MM: both comparisons report a modification. Inspect both diffs.??: the file is untracked and does not appear in the normal tracked-file comparisons above.
An empty plain diff with M is expected: the staged snapshot and working file agree. With MM, an empty git diff HEAD can mean the working file has returned to the committed content while the index has not.
If the symptom is a tracked file appearing despite an ignore rule, use the gitignore tracking diagnostic instead. Ignore rules and diff comparison endpoints solve different problems.
Reproduce the empty HEAD comparison
This disposable fixture was executed during article verification on October 3, 2026, using git version 2.54.0 (Apple Git-157) on macOS. It covers an ordinary text file in a repository with an existing commit. It does not test merge conflicts, submodules, sparse checkouts, or custom diff drivers.
Run the following in Bash, separately from your project. The final commit exists only in the temporary repository; no remote is configured.
set -eufixture_dir="$(mktemp -d)"git init -q -b main "$fixture_dir"cd "$fixture_dir"git config user.name Fixturegit config user.email fixture@example.invalidprintf 'theme=light\n' > settings.txtgit add -- settings.txtgit -c commit.gpgsign=false commit -qm "Baseline"
printf 'theme=dark\n' > settings.txtgit add -- settings.txtprintf 'plain diff after add:\n'git --no-pager diff -- settings.txtprintf 'cached diff after add:\n'git --no-pager diff --cached -- settings.txt
printf 'theme=light\n' > settings.txtprintf 'status after reversing the working edit:\n'git status --shortprintf 'diff HEAD:\n'git --no-pager diff HEAD -- settings.txtprintf 'cached diff:\n'git --no-pager diff --cached -- settings.txtprintf 'unstaged diff:\n'git --no-pager diff -- settings.txtprintf 'index contents:\n'git show :settings.txt
git -c commit.gpgsign=false commit -qm "Commit the staged snapshot"printf 'committed contents:\n'git show HEAD:settings.txtprintf 'working contents:\n'cat settings.txtgit status --shortprintf 'fixture: %s\n' "$fixture_dir"After the first git add, plain diff printed nothing and cached diff showed light changing to dark. After the working file was manually changed back, the observed state was:
| Location | Contents |
|---|---|
| HEAD | theme=light |
| Index | theme=dark |
| Working file | theme=light |
Status printed MM settings.txt. The HEAD comparison printed nothing, while cached diff contained:
theme=lighttheme=darkThe unstaged diff showed the reverse:
theme=darktheme=lightThe two changes cancel when comparing the endpoints, but the staged snapshot still differs. The final ordinary commit recorded theme=dark; the file on disk remained theme=light, and status then printed M settings.txt. An empty HEAD diff before committing had not established that the next commit would be empty.
Review the snapshot you intend to commit
For an ordinary commit without path arguments or -a, review the whole staged diff, then inspect the intended paths:
git diff --cached --name-statusgit diff --cachedgit show :settings.txtIf the staged version is the one you want, further edits can remain unstaged. If the current working version is the one you want, stage that exact file again and inspect the result:
git add -- settings.txtgit diff --cached -- settings.txtgit status --shortIn the fixture’s pre-commit state, staging theme=light again would make the index match HEAD and remove that file’s pending change. A separate verification run repeated the fixture up to its pre-commit state, staged the working file again, and confirmed an empty cached diff and clean status. The fixture above instead demonstrates committing the earlier staged version.
Git’s commit reference describes other commit forms that change the selection: -a stages modifications and deletions of tracked files, while explicit path arguments select those working-tree contents. Therefore, the cached diff is a preview of the ordinary reviewed-index commit, not every possible commit command.
Use git diff --cached to inspect the next staged snapshot and git diff to inspect edits after staging. Keep git diff HEAD for the net working-file comparison; an empty result there is insufficient evidence that nothing is staged.
References: