Understanding the Unified Diff Format
A deep dive into the unified diff format — how to read @@ headers, interpret +/- lines, understand context lines, and work with patch files.
Priya Sharma
Platform Engineer
What Is the Unified Diff Format?
The unified diff format, introduced in GNU diffutils 1.15, is the standard interchange format for patches in software development. When you run git diff, send a patch to a mailing list, or review a pull request, you're reading unified diff format. Understanding it deeply will make you a faster, more confident developer.
The Anatomy of a Unified Diff
Here's a complete example with every element labeled:
--- a/src/auth.ts (1)
+++ b/src/auth.ts (2)
@@ -42,7 +42,8 @@ (3)
function login(email: string, password: string) { (4)
- const user = db.findByEmail(email) (5)
+ const user = await db.findByEmail(email) (6)
+ if (!user) throw new AuthError('User not found') (7)
return generateToken(user) (8)
}
- --- a/src/auth.ts — the "before" file (original)
- +++ b/src/auth.ts — the "after" file (modified)
- @@ -42,7 +42,8 @@ — the hunk header (explained below)
- Lines starting with a space — context lines (unchanged)
- Lines starting with
-— removed lines - Lines starting with
+— added lines - Another added line
- More context
Decoding the @@ Header
The hunk header @@ -42,7 +42,8 @@ is the most misunderstood part of the format. Here's how to read it:
- -42,7 — In the original file, this hunk starts at line 42 and spans 7 lines
- +42,8 — In the modified file, this hunk starts at line 42 and spans 8 lines
The span counts all lines in the hunk: context lines + added lines for the + side, context lines + removed lines for the - side. The difference in spans (8 vs 7) tells you the net change: one line was added.
Some diffs also include a function context after the second @@ — like @@ -42,7 +42,8 @@ function login — which is just a hint about what scope you're in, not part of the format.
Context Lines
By default, diff includes 3 lines of context around each change. Context lines serve two purposes:
- Readability — you can understand what changed without reading the whole file
- Patch application — when applying a patch, the context lines are used to locate the correct position in the file, making patches robust against minor version differences
You can control context with diff -U5 (5 lines) or git diff -U0 (no context, just the changes).
Multi-File Patches
A real patch file often modifies multiple files. Each file's changes begin with a new --- / +++ header. A typical patch looks like:
diff --git a/package.json b/package.json
--- a/package.json
+++ b/package.json
@@ -3,7 +3,7 @@
- "version": "1.2.0",
+ "version": "1.3.0",
diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+## v1.3.0 (2025-02-05)
+- Added OAuth support
+- Fixed rate limiting bug
+
## v1.2.0
Applying Patches
Once you have a .patch file, apply it with:
# Apply a patch
patch -p1 < changes.patch
# Apply a git-formatted patch
git apply changes.patch
# Apply and create a commit
git am changes.patch
The -p1 flag strips one leading path component from filenames (removing the a/ and b/ prefixes git adds).
Creating Patches
# Compare two files
diff -u original.ts modified.ts > changes.patch
# Export a git commit as a patch
git format-patch HEAD~1
# Export a range of commits
git format-patch origin/main..HEAD
Understanding the unified diff format makes you more effective at code review, debugging, and maintaining open-source projects. The next time you see a @@ header, you'll know exactly what it means.
Share this article
Was this article helpful?
Ready to try it? Start a free comparison →
Priya Sharma
Platform Engineer
Priya Sharma writes about developer tools, software engineering best practices, and productivity for the DiffChecker Pro blog. With extensive experience in software development, Priya focuses on practical guides that help developers work more effectively.