Core answer: A diff shows the minimal line-level changes between two texts: − lines removed, + lines added, unchanged lines as context. Unified diff format (diff -u) with 3 lines of context is the standard; git calls it a "patch". Two files differing in one line show ~7 lines of output (hunk header + context + the change). Diffs work line-by-line, so reflowed paragraphs look fully rewritten — normalize formatting before diffing prose.
Reading a unified diff
@@ -3,7 +3,7 @@ means: from old file line 3, show 7 lines; new file line 3, 7 lines. Lines prefixed " " are context, "−" old-only, "+" new-only. One hunk per changed region; distant changes get separate hunks.
The algorithms under the hood
- Myers algorithm (git default): finds the shortest edit script — minimal insertions/deletions. O(ND) time, which is why huge files diff slowly.
- Histogram/patience (git options): better on code with repeated lines (braces); often produces more intuitive hunks.
- Word/char diff: same algorithms on word or character tokens — what "git diff --word-diff" and online text-compare tools use.
Worked examples
Example 1 — Code review. A PR showing +127 −3 with 120 lines being an auto-formatter: ask to split format-only changes from logic changes, or review with "hide whitespace" (GitHub's w=1).
Example 2 — Config drift. Production nginx.conf vs repo version: diff reveals a manually added client_max_body_size 50m that never made it to git — the classic snowflake-server catch.
Example 3 — Contract comparison. Two versions of a contract, word-diffed: one changed "shall" to "may" — a single word worth millions; character-level diff catches what eyes skim past.
Example 4 — Merge conflicts. Conflict markers <<<<<<< / ======= / >>>>>>> show YOUR side vs THEIR side of the same lines; resolve by editing to the intended final state, then deleting all markers.
Common mistakes and myths
- Diffing minified/generated files — bundle.js diffs are noise; add generated files to .gitignore or mark them linguist-generated.
- Whitespace wars — mixed tabs/spaces or CRLF/LF make every line "changed"; standardize via .gitattributes + editorconfig before mass commits.
- Trusting line-diff for prose — one reflowed paragraph diffs as 100% changed; use word-diff for documents.
- Assuming diff = semantic — two programs with identical diffs can behave differently (moved code across scopes); diff shows text, not meaning.
- Binary blindness — diff can't show image/XLSX changes; use specialized tools (image diff overlays, spreadsheet comparators) or accept "files differ".