Unified Diff Format Explained
What Is Unified Diff?
Unified diff is the standard format for representing differences between two versions of a text file. Created for the diff -u command in Unix, it became the universal format adopted by Git, Mercurial, Subversion, and every major patch tool. If you have ever run git diff, you have already read unified diff output.
The format is designed to be both human-readable and machine-parseable — you can see what changed at a glance, and tools can apply the same diff as a patch to transform one file into another.
Anatomy of a Unified Diff
Here is a typical unified diff:
--- a/src/utils/format.js
+++ b/src/utils/format.js
@@ -12,7 +12,7 @@ function formatDate(date) {
const year = date.getFullYear();
const month = date.getMonth() + 1;
const day = date.getDate();
- return `${year}-${month}-${day}`;
+ return `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
}
function parseDate(str) {
Let us break it down piece by piece.
File Headers
--- a/src/utils/format.js
+++ b/src/utils/format.js
---marks the original file (often prefixed witha/in Git).+++marks the modified file (prefixed withb/).
Hunk Headers
@@ -12,7 +12,7 @@ function formatDate(date) {
The @@ line is the hunk header. It tells you where this chunk of changes lives:
-12,7— in the original file, this hunk starts at line 12 and spans 7 lines.+12,7— in the modified file, this hunk starts at line 12 and spans 7 lines.- The trailing
function formatDate(date)is a context line pulled from the file to help you locate the change visually.
Change Lines
| Prefix | Meaning |
|---|---|
| (space) | Context line — unchanged, shown for reference |
- | Line removed from the original |
+ | Line added in the modified version |
A line that was modified appears as both a - removal and a + addition — the old content followed by the new content.
Reading Multi-Hunk Diffs
Large changes produce multiple hunks separated by their own @@ headers:
@@ -1,5 +1,6 @@
import { format } from './format';
+import { validate } from './validate';
const data = getData();
-const result = format(data);
+const result = format(validate(data));
export default result;
@@ -22,3 +23,8 @@
return output;
}
+
+export function validate(input) {
+ if (!input) throw new Error('Empty input');
+ return input;
+}
Each hunk operates independently — line numbers are relative to that hunk's position, not the entire file.
Context Lines
By default, unified diff shows 3 lines of context before and after each change. This helps you understand the surrounding code without opening the file. You can control the context width:
diff -U 5 old.txt new.txt # 5 lines of context
diff -U 0 old.txt new.txt # no context, just changes
Git respects this via the -U flag as well:
git diff -U 10 # 10 lines of context
Generating and Applying Patches
Unified diff output can be saved as a patch file and applied to the original:
# Generate a patch
git diff > feature.patch
# Apply it
git apply feature.patch
This is how open-source projects accept contributions via email — contributors send unified diffs, maintainers review them, and apply them to the tree.
Binary and Special Cases
Unified diff is a text format. Binary files (images, compiled files) cannot be represented this way. Git marks them differently:
Binary files a/logo.png and b/logo.png differ
New or deleted files use /dev/null as one side:
--- /dev/null
+++ b/new-file.js
@@ -0,0 +1,3 @@
+export function hello() {
+ return 'world';
+}
Practical Tips
- Line numbers can shift — after the first hunk, line numbers in subsequent hunks refer to the modified file, not the original. Do not try to correlate line numbers across hunks.
- Whitespace changes — trailing whitespace in removed/added lines is significant. Use
git diff -wto ignore whitespace changes. - Renamed files — Git detects renames and shows them as
--- a/old-name.js/+++ b/new-name.js. - Combined diffs — merge commits produce a combined diff format with a third column prefix for the second parent.
Key Takeaways
- Unified diff is the standard format for representing text changes, used by Git and all major version control systems.
- Each diff contains file headers (
---/+++), hunk headers (@@), context lines (space prefix), removals (-), and additions (+). - Hunk headers report start line and span for both the original and modified file.
- Modified lines appear as a
-removal followed by a+addition. - Context lines provide surrounding code for orientation without opening the file.
- Unified diffs double as patch files — save the output and apply it with
git apply.
Try It Yourself
Paste two versions of text and see the unified diff instantly with the Diff Checker.