DevToolsForYou
Text Processing

How to Read a Diff

A practical guide to reading unified diffs — understand the +/- notation, hunk headers, file headers, and how diffs appear in git, pull requests, and patch files.

2 min readUpdated Apr 11, 2026

What is a diff?

A diff (short for difference) is a representation of the changes between two versions of text. The most common format is the unified diff, produced by the diff -u command on Unix systems and used by git diff, GitHub pull requests, and patch files. It shows exactly which lines were removed and which were added.

Anatomy of a unified diff

A unified diff has four types of lines. The file headers identify the original and new files. Hunk headers (@@ lines) mark each changed region. Lines prefixed with - were in the original and are being removed. Lines prefixed with + are new additions. Context lines (no prefix, usually 3 before and after) show surrounding unchanged code.

diff
--- a/src/greeting.js     ← original file
+++ b/src/greeting.js     ← new file
@@ -4,7 +4,7 @@           ← hunk header (explained below)
 
 function greet(name) {
-  return "Hello, " + name;   ← removed line
+  return `Hello, ${name}!`;  ← added line
 }
 
 module.exports = { greet };

Reading the @@ hunk header

The @@ line tells you which line numbers the change covers. The format is @@ -originalStart,originalCount +newStart,newCount @@. The - side describes the original file and the + side describes the new file.

text
@@ -4,7 +4,7 @@
     ↑  ↑  ↑  ↑
     |  |  |  └─ 7 lines from the new file starting at line 4
     |  |  └──── new file starts at line 4
     |  └─────── 7 lines from the original file starting at line 4
     └────────── original file starts at line 4

@@ -12,4 +15,6 @@  ← 4 lines removed starting at line 12; 6 lines added starting at line 15

git diff output

git diff shows unstaged changes, git diff --staged shows staged changes, and git diff HEAD shows everything since the last commit. The file header is slightly different — it shows the git object hash (a/ and b/ prefixes are git conventions, not filesystem paths).

bash
# Common git diff commands
git diff                  # unstaged changes vs working tree
git diff --staged         # staged changes vs last commit
git diff HEAD             # all changes vs last commit
git diff main feature     # difference between two branches
git diff abc123 def456    # difference between two commits
git diff -- path/to/file  # diff a specific file only

Applying a patch file

A .patch file is just a saved unified diff. The patch command applies it to your files. The -p1 flag strips one level of directory prefix (the a/ and b/ that git adds).

bash
# Create a patch from git
git diff > my-changes.patch
git format-patch HEAD~1   # create a patch from the last commit

# Apply a patch
patch -p1 < my-changes.patch

# Check if a patch will apply cleanly (dry run)
patch -p1 --dry-run < my-changes.patch
Frequently asked questions

What does a line with no prefix mean in a diff?

Lines with no prefix (called context lines) are unchanged. They are included to show the surrounding code so you can understand where the change happened. By default, diff shows 3 context lines on each side of a change.

What is the difference between a unified diff and a side-by-side diff?

A unified diff (the standard format) interleaves removed and added lines in a single column with - and + prefixes. A side-by-side diff shows the original and new versions in parallel columns. Both convey the same information — side-by-side is often easier to read for large changes.

Why does my diff show changes to every line even though I only changed whitespace?

Whitespace-only changes are real changes at the byte level. Use diff -b (ignore trailing whitespace) or diff -w (ignore all whitespace) to suppress them. In git, use git diff -w or git diff --ignore-space-change.

Related guidesAll guides →