open atlas
↑ Back to track
Git, from zero to senior GIT · 02 · 02

Reading diffs and the log

git diff shows working tree vs index; git diff --staged shows index vs HEAD; git diff HEAD shows everything since the last commit. Learn to read a unified diff hunk — the @@ header and the +/- lines — and to browse history with git log, --oneline, --graph, and git show.

GIT Junior ◷ 17 min
Level
FoundationsJuniorMiddleSenior

Before you commit, you should be able to answer one question with certainty: what exactly am I about to record? Staging blindly is how secrets, debug prints, and stray edits leak into history. Git answers that question precisely with git diff — and answers “what changed across the whole project, and when?” with git log.

By the end of this lesson you will be able to read a unified diff hunk line by line, pick the right diff variant for what you want to compare, and navigate project history with log and show.

Goal

After this lesson you can distinguish git diff, git diff --staged, and git diff HEAD, read a unified diff hunk including its @@ header and +/-/context lines, and browse history with git log --oneline --graph and git show.

1

git diff with no arguments compares your working tree against the staging area — the changes you have NOT staged yet. This is the most common diff and the one beginners misread. It does not show everything you changed since the last commit; it shows only what is still unstaged:

git diff

Once you git add a change, it disappears from plain git diff (it is now staged) and you need a different variant to see it. That surprise — “I edited the file, why is the diff empty?” — almost always means you already staged it.

2

Three diff variants compare three different pairs of snapshots. Pick by what you want to see:

git diff            # working tree vs index  → unstaged changes
git diff --staged   # index vs HEAD          → what a commit would record (also --cached)
git diff HEAD       # working tree vs HEAD    → all changes since last commit (staged + unstaged)

HEAD is the latest commit on your current branch. git diff --staged is the one to run right before committing — it shows exactly what the commit will contain, nothing more. git diff HEAD is the big picture: everything different from the last commit regardless of staging.

3

A unified diff is read as a set of hunks, each with a header and three kinds of lines. Here is one hunk:

@@ -12,6 +12,7 @@ function login(user) {
   const token = sign(user);
-  return token;
+  log.debug("issued token");
+  return token;
 }

The @@ -12,6 +12,7 @@ header is the map: -12,6 means “the old file, starting at line 12, spanning 6 lines”; +12,7 means “the new file, starting at line 12, spanning 7 lines”. After it: a leading space is unchanged context, a - is a line removed, a + is a line added. A modified line shows as a - (old) immediately followed by a + (new). Read top to bottom and you reconstruct the edit exactly.

Why this works

Why the line counts in the header? Tools and humans use them to apply or locate a hunk even if surrounding code has shifted. The context lines (the unchanged ones around the change) let git re-find the right spot in a file that has been edited elsewhere since the diff was generated — this is what makes patches portable. When you review a diff, the context is not noise; it is the anchor that proves the change is where you think it is.

4

git log lists history; flags turn a wall of text into a readable map. The raw log is verbose, so seniors almost always shape it:

git log                            # full entries: hash, author, date, message
git log --oneline                  # one compact line per commit
git log --oneline --graph --all --decorate   # ASCII branch graph across all branches

--oneline collapses each commit to a short hash plus subject; --graph draws the branch/merge structure; --all includes every branch, not just the current one; --decorate shows which branch and tag names point where. This combination is the single most useful way to see “what is the shape of this repo’s history?”

5

git show inspects one commit in full — its metadata plus its diff. When log tells you which commit you care about, show tells you what it did:

git show <commit>         # that commit's message and its full diff
git log -p                # every commit's full diff, newest first
git log --stat            # per-commit summary: files touched, +/- line counts

git show abc1234 prints the author, date, message, and the exact hunks that commit introduced — the fastest way to answer “what did this commit actually change?”

Worked example

Catching a debug line before it ships.

You fixed a bug in auth.js and want to commit. First you stage and look:

git add auth.js
git diff --staged

The output shows the hunk from Step 3 — your real fix, but also a stray + log.debug("issued token"); you added while debugging. Because you read the --staged diff, you catch it before it enters history. You unstage and remove that line, then re-check:

git diff --staged   # now shows only the real fix
git commit -m "Fix token issuance in login"

Later, a teammate asks what that commit changed. You run git log --oneline to find its hash, then git show <hash> to print the exact hunk — no guessing, no opening files. Reading diffs is what kept the debug line out and what answers the question months later.

Common mistake

A frequent confusion: running git diff after git add and seeing nothing, then concluding “my change vanished.” It did not — it moved to the staged side. Plain git diff only ever shows the gap between working tree and index. After staging, use git diff --staged (index vs HEAD) or git diff HEAD (everything since the last commit). Knowing which pair each command compares is the whole skill.

Check yourself
Quiz

You edited a file and ran git add on it. You now want to see precisely what your next commit will record. Which command shows that?

Recap

git diff (no args) compares working tree vs index — your unstaged changes; git diff --staged compares index vs HEAD — exactly what the next commit will record; git diff HEAD compares working tree vs HEAD — everything since the last commit. A unified diff is read as hunks: the @@ -a,b +c,d @@ header maps old and new line ranges, a leading space is context, - is removed, + is added. Browse history with git log, shaped by --oneline, --graph, --all, and --decorate; inspect a single commit with git show, and add -p or --stat to the log for per-commit diffs or summaries. Next you will tell git which files to ignore entirely with .gitignore.

Practice

Start at the top. Tasks go easiest → hardest: recall a fact, apply it to a case, then a senior-level stretch. Open one, attempt it, then reveal.

recallapplystretch0 of 4 done

Something unclear?

Ask a question about this lesson. Questions are anonymous and go straight to the author to make the lesson better.

shortcuts expand
search
K
prev piece
k
next piece
j
cycle tier
t
this menu
?
sources2
expand
  1. 01
  2. 02

Trademarks belong to their respective owners. Editorial reference only.