Git Course 0%

git diff in three forms

Beginner Git CLI VS Code UI IntelliJ UI GitLab UI GitHub UI ≈ 12 min

What you will learn

  • The three comparisons: working tree vs staging, staging vs last commit, commit vs commit
  • How to read a diff: file headers, hunk headers, minus and plus lines, context
  • The --stat and --word-diff views, and how each tool shows the same thing

After this lesson you can

  • I can answer "what exactly did I change?" at any moment, for any file
  • I read a diff without being distracted by the header lines

Why this matters

git status names the files that changed; git diff shows the lines. It is the difference between "README.md modified" and "the word tiny became small on line 3". Reading your own diff before every commit is the single habit that most reduces embarrassing merge requests, and reading other people's diffs is what review is.

The three comparisons

Every diff compares two of the areas from lesson 2.2:

Command Compares Answers
git diff working tree vs staging area What have I changed that is not staged yet?
git diff --staged (or --cached) staging area vs last commit What will the next commit contain?
git diff <a> <b> commit a vs commit b What changed between two points in history?

And git diff HEAD compares the working tree with the last commit, staged or not: everything since your last commit.

Reading a diff

Ana changed one word in README.md and added a question to docs/faq.md. Nothing is staged yet:

Terminal
$ git diff
diff --git a/README.md b/README.md
index 19ed536..6516ba6 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
 # Trailguide
 
-A tiny command-line program that prints hiking trail information for the **Northwind Trails** guide.
+A small command-line program that prints hiking trail information for the **Northwind Trails** guide.
 It exists so that people learning Git have something realistic to practice on: documentation to edit,
 data to update, a small program to run, and tests that can pass or fail.
 
diff --git a/docs/faq.md b/docs/faq.md
index 9c0d4c8..9a42534 100644
--- a/docs/faq.md
+++ b/docs/faq.md
@@ -30,3 +30,7 @@ Not yet. It is planned for 1.3.
 ## Can I add my own trail?
 
 Yes: add a line to data/trails.csv.
+
+## Can I use the data elsewhere?
+
+Yes, the CSV is public domain.
Part Meaning
diff --git a/README.md b/README.md One block per file; a/ is the old version, b/ the new
index 19ed536..6516ba6 100644 Internal ids of the two versions and the file mode; safe to ignore
--- a/… / +++ b/… Which side is which
@@ -1,6 +1,6 @@ A hunk header: old lines 1–6 became new lines 1–6. A file can have several hunks
lines starting with a space Context: unchanged lines around the change
- line Removed
+ line Added

A changed line appears as a - line followed by a + line, because Git compares whole lines. The second hunk, @@ -30,3 +30,7 @@, shows three old lines becoming seven: four added, nothing removed. The text after the @@ is Git's guess at the nearest heading, to help you orient.

The three forms in action

Stage the README and compare again:

Terminal
$ git add README.md
$ git diff
diff --git a/docs/faq.md b/docs/faq.md
index 9c0d4c8..9a42534 100644
--- a/docs/faq.md
+++ b/docs/faq.md
@@ -30,3 +30,7 @@ Not yet. It is planned for 1.3.
 ## Can I add my own trail?
 
 Yes: add a line to data/trails.csv.
+
+## Can I use the data elsewhere?
+
+Yes, the CSV is public domain.

The README vanished from git diff: working tree and staging area agree about it now. It moved to the other side:

Terminal
$ git diff --staged
diff --git a/README.md b/README.md
index 19ed536..6516ba6 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
 # Trailguide
 
-A tiny command-line program that prints hiking trail information for the **Northwind Trails** guide.
+A small command-line program that prints hiking trail information for the **Northwind Trails** guide.
 It exists so that people learning Git have something realistic to practice on: documentation to edit,
 data to update, a small program to run, and tests that can pass or fail.
 

This is exactly what git commit would record right now. And everything since the last commit, regardless of staging:

Terminal
$ git diff HEAD --stat
 README.md   | 2 +-
 docs/faq.md | 4 ++++
 2 files changed, 5 insertions(+), 1 deletion(-)

--stat summarizes instead of listing lines: files, and a bar of + and -. Use it first on big changes, then read the files that matter.

Word-level diffs

For prose, whole-line diffs hide the actual edit. --word-diff marks words instead:

Terminal
$ git diff --staged --word-diff
A [-tiny-]{+small+} command-line program that prints hiking trail information for the **Northwind Trails** guide.

[-removed-] and {+added+}. Documentation writers use this constantly; GitLab and GitHub offer the same as a toggle in their diff views.

Between commits

Any two commits, branches or tags can be compared, optionally for one file:

Terminal
$ git diff HEAD~1 HEAD                 # the last commit's change
$ git diff v1.2.0 main --stat          # everything since the release, summarized
$ git diff HEAD~3 HEAD -- docs/faq.md  # one file across three commits

The -- separates commits from paths, so Git never confuses a file called main with the branch.

In the tools

Everything above. Two more useful flags: git diff --color-words is a lighter word diff; git diff --stat for the summary. Long diffs open in the pager: Space scrolls, q quits.

Common mistakes

  • git diff shows nothing, so "there are no changes". They may be staged. git diff --staged, or git diff HEAD for both.
  • Reading the header lines as changes. Only - and + lines are changes.
  • Whole-file diffs from reformatting or line endings. --stat reveals it (hundreds of lines for a one-word edit); lesson 4.5 explains.
  • Forgetting -- before a path that looks like a branch name.

Try it yourself

Goal: see the same change move from one diff form to the other.

  1. In the playground, change one word in README.md and add two lines to docs/faq.md.
  2. Run git diff --stat, then git diff.
  3. Stage the README only; run git diff --stat and git diff --staged --stat.
  4. Run git diff --staged --word-diff to see the changed word.

Expected result: step 2 lists both files; after staging, git diff lists only the FAQ and --staged only the README; --word-diff shows [-old-]{+new+}.

Show solution

The README moved from the unstaged diff to the staged diff the moment you ran git add. git diff HEAD --stat would still show both, because it ignores the staging boundary and compares with the last commit. Clean up with git restore --staged README.md && git restore README.md docs/faq.md, or commit.

Check yourself

1. Which command shows exactly what the next git commit will record?
2. In a diff, what does @@ -30,3 +30,7 @@ mean?
3. GitLab's merge request "Changes" tab corresponds to…

Key terms

Diff Working tree Staging area Commit