Learning Objectives
By the end of this lesson you will be able to:
- Read a diff hunk and interpret
+,-, and@@lines - Explain the difference between
git diffandgit diff --staged - Diagnose the "git diff shows nothing" confusion
- Compare any two commits to see exactly what changed between builds
What a Diff Is
git log tells you that something changed. git diff tells you what.
git diff
diff --git a/config/test-env.yaml b/config/test-env.yaml
index 3a4f1c2..8b7e9d1 100644
--- a/config/test-env.yaml
+++ b/config/test-env.yaml
@@ -12,7 +12,7 @@ database:
host: staging-db.internal
port: 5432
- timeout_seconds: 30
+ timeout_seconds: 5
pool_size: 10
Ignore the first three lines — they're headers naming the file and its internal object ids. The content is everything after @@:
@@ -12,7 +12,7 @@— the hunk header. This block starts at line 12 and covers 7 lines, in both the old version (-) and the new one (+).- Lines starting with
-— removed. This was in the old version. - Lines starting with
+— added. This is in the new version. - Lines with a leading space — unchanged, shown for context so you can see where you are.
A modified line always appears as a pair: the old one removed, the new one added. Git doesn't track "edits", only removals and additions.
Read that example as a tester and something should jump out: the database timeout dropped from 30 seconds to 5. That's a one-word change with a real chance of causing intermittent failures on a slow environment — and no release note would ever have mentioned it.
The Two Diffs That Matter
This is the single most common point of confusion in this whole trail, and it's genuinely simple once stated plainly. git diff compares two of the three trees — and which two depends on the flag.
| Command | Compares | Answers |
|---|---|---|
git diff |
working directory ↔ staging area | "What have I changed but not yet staged?" |
git diff --staged |
staging area ↔ last commit | "What's about to go into my next commit?" |
git diff HEAD |
working directory ↔ last commit | "What have I changed since the last commit, staged or not?" |
--cached is an older synonym for --staged; they are identical.
The Classic Confusion
You edit a file. You run git add. You run git diff to check your work — and Git prints nothing.
Nothing broke. git diff with no arguments compares the working directory to the staging area, and you just made those identical by staging the file. There is genuinely no difference between them to show.
What you wanted was:
git diff --staged
The rule of thumb: before git add, use git diff. After git add, use git diff --staged. Or just use git diff HEAD, which shows everything you've done since the last commit regardless of what's staged.
Comparing Commits
Diffs aren't limited to uncommitted work. Any two points in history can be compared:
git diff 4e9d331 4f2a1c9
That's the complete change between two commits — which, if those are the previous build and the current one, is the exact scope of what you need to test.
To narrow it to the part you care about:
git diff 4e9d331 4f2a1c9 -- src/payments/
And for a file-level summary — which files changed and how much each one changed, without the line-by-line detail:
git diff --stat 4e9d331 4f2a1c9
src/payments/currency.py | 24 ++++++++++++++++-------
config/test-env.yaml | 2 +-
tests/test_checkout.py | 41 +++++++++++++++++++++++++++++++++++
3 files changed, 60 insertions(+), 7 deletions(-)
For a tester, --stat is often the more valuable view: it's a change map at a glance, telling you which areas of the product are in play today.
Pro Tip:
git diffin the terminal is fine for small changes and painful for large ones. Every serious editor — VS Code, IntelliJ, PyCharm — has a built-in side-by-side diff viewer that reads the same data. Use the terminal to find the change, and the editor to study it.
Key Takeaways
- A diff shows removed lines with
-, added lines with+, and unchanged context with a leading space - The
@@hunk header gives the line numbers, so you know where in the file you are git diffcompares working directory to staging area;git diff --stagedcompares staging to the last commit- Seeing nothing from
git diffaftergit addis expected, not a bug — use--stagedorHEAD git diff <commit-a> <commit-b>shows the full change between two builds;--statreduces it to a file-level summary