How to Read a Diff
What the symbols in a unified diff mean, how to read git diff output, and what the hunk header tells you.
What is a diff?
A diff (short for difference) is a representation of what changed between two versions of a file — or two text inputs. It shows exactly which lines were added, removed, or left unchanged, without including the entire file.
The unified diff format is the standard used by Git, most code review tools (GitHub, GitLab, Gerrit), and the Unix diff command. Once you know how to read it, you can understand any code change, patch file, or pull request at a glance.
A complete example
diff --git a/src/utils.js b/src/utils.js
index 4b2f1a3..8e9d7c1 100644
--- a/src/utils.js
+++ b/src/utils.js
@@ -12,7 +12,9 @@ function formatDate(date) {
const month = date.getMonth() + 1
const day = date.getDate()
- return month + '/' + day + '/' + date.getFullYear()
+ const year = date.getFullYear()
+ const pad = n => String(n).padStart(2, '0')
+ return pad(month) + '/' + pad(day) + '/' + year
}
module.exports = { formatDate }Reading the header
diff --git a/src/utils.js b/src/utils.js
The file being compared. a/ is the "before" version, b/ is the "after" version. For a new file, a/ doesn't exist; for a deleted file, b/ doesn't exist.
--- a/src/utils.js +++ b/src/utils.js
--- marks the old file, +++ marks the new file. These lines tell you which file each subsequent - and + line comes from.
The hunk header
@@ -12,7 +12,9 @@ function formatDate(date) {This is called the hunk header. It tells you where in the file the change occurs:
-12,7 — in the old file, this hunk starts at line 12 and spans 7 lines
+12,9 — in the new file, this hunk starts at line 12 and spans 9 lines (2 more because we added 2 lines)
function formatDate(date) { — the surrounding context function, shown for orientation (Git infers this from the nearest function/class declaration)
Line markers
(space)-+A "modification" to a line always appears as a removal followed by an addition — diffs don't have a "modified" concept, only added and removed lines.
Common git diff commands
# Changes in your working tree (unstaged) git diff # Staged changes (what will be committed) git diff --staged # Changes in a specific commit git show <commit-hash> # Changes between two commits git diff main..feature-branch # Changes to a specific file only git diff HEAD -- src/utils.js # Word-level diff (highlights changed words, not lines) git diff --word-diff
Frequently asked questions
- What does 'no newline at end of file' mean in a diff?
- Most text editors and tools expect files to end with a newline character. If a file doesn't, git diff shows "\ No newline at end of file" after the last line. It's usually harmless but can cause noise in diffs — many linters and editors will add the trailing newline automatically.
- What is a patch file?
- A patch file is a diff saved to a file — typically with a .patch extension. You can create one with git diff > my-change.patch and apply it later with git apply my-change.patch or the Unix patch command. Patch files were the original way to share code changes before distributed version control systems (like Git) made branches and PRs the norm.
- How do I make git show only the changed words, not full lines?
- Use git diff --word-diff. Instead of showing entire added/removed lines, it highlights the specific words that changed inline. This is especially useful for prose or documentation changes where line rewrapping obscures what actually changed.