git diff: what exactly changed
Updated July 31, 2026
git diff shows the difference line by line: which lines went away, which ones appeared, and where in the file it happened.
git status answers the question "which files were touched". git diff answers "what inside them was touched". Read its output before every commit: it is your last chance to notice that something extra is riding along into the snapshot.
$ git diff
diff --git a/report.txt b/report.txt
index 98679e4..3394999 100644
--- a/report.txt
+++ b/report.txt
@@ -1,4 +1,5 @@
Q3 report
-Sales grew.
+Sales grew by 12%.
We hired two people.
+Next quarter's budget is approved.The first four lines are the header: the file name, short names of git's internal objects, and the file mode. The useful part is below.
The @@ -1,4 +1,5 @@ line says which chunk of the file is shown: on the left there were four lines starting at line one, on the right there are now five. Such a chunk is called a hunk, and a large file has several of them. Then come the lines themselves. A leading space means the line did not change and is shown for context. A - means the line was there before and is gone now. A + means it appeared. An edit inside a line shows up as a minus and a plus together: half a line does not exist as far as git is concerned.
Working directory, index, and commit
There are three areas, and a diff always compares two of them.
$ git add report.txt
$ git diff # empty: the working directory matches the index
$ git diff --staged # exactly what will go into the next commit
$ git diff HEAD # everything: staged and unstaged togetherA silent git diff right after git add is alarming: the changes look gone. They moved into the index (the staging area), and --staged is what shows them now.
Between commits and branches
The same command compares any two points of the history:
$ git diff 7cb799b ab941c9 # between two commits
$ git diff HEAD~1 HEAD # the last commit against the one before
$ git diff main draft # branch against branch
$ git diff main draft -- report.txt # the same, but for one file onlyWhen there are too many lines, the per-file summary reads faster:
$ git diff --stat main draft
report.txt | 2 ++
1 file changed, 2 insertions(+)Common mistakes
The order of the arguments matters: git diff A B shows what has to be done to A to end up with B, not the other way round. A new file will not show up at all until git knows about it: diff does not compare untracked files, they appear only in git status. And on a long file the output opens in a pager, which you leave with q.
Where this is in the book
The full treatment is in Chapter 4. Inspect, undo, ignore. Next to it, git status and git log are worth a look.
To practise it by hand, take the interactive lesson Undoing changes.