A text diff compares two pieces of text and highlights what changed. The tool above runs the comparison in your browser; nothing leaves your machine. The interesting question is how a diff is computed — there’s no single right answer, and different tools make different tradeoffs.
The core problem
Given two sequences of lines, find the shortest edit script — the smallest set of insertions and deletions — that turns the first into the second. Equivalently: find the longest common subsequence (LCS), then everything not in the LCS is a change.
A: The quick brown fox
jumps over the lazy dog
and runs away
B: The quick brown fox
leaps over the lazy dog
and runs away
The LCS is lines 1 and 3. Line 2 differs, so the diff reports: line 2 deleted from A, line 2 inserted in B.
Myers’ diff algorithm
The standard line-diff algorithm is Myers’ diff, published in 1986 — it’s what git diff, diff -u, and most text editors use. It runs in O((N+M)D) time where D is the number of differences. When the inputs are mostly similar (small D), it’s near-linear; when they’re entirely different (large D), it degrades to roughly O(N²).
Myers’ produces the minimum edit script, but minimum isn’t always the most readable. Two changes inside a function can be reported as “delete the whole function, insert a new function” if that’s shorter than reporting the individual line changes. Tools like git --histogram-diff and git --patience-diff use heuristics to prefer human-readable diffs over strictly minimal ones.
Line, word, character
Most diff tools operate at multiple granularities:
| Level | Compares | Used for |
|---|---|---|
| Line | Whole lines as atoms | Code review, version control |
| Word | Whitespace-delimited tokens | Prose editing, when whitespace is meaningful only at word boundaries |
| Character | Individual characters | Tight edits where a typo or single-character change matters |
The standard approach: do a line diff first to find changed regions, then do a word or character diff inside the changed regions to highlight what specifically moved. This is what git diff --word-diff and editor “inline diff” views do.
Unified vs side-by-side
Two ways to render a diff:
- Unified diff — the classic
+/-per line format, with a few lines of context. Compact, scriptable. The formatgit diffanddiff -uemit. Easy to copy into a code review. - Side-by-side — two columns, original on the left, modified on the right, changes highlighted. Easier to scan for human review, especially when changes are large or spread out.
The tool above uses a unified-style view: line mode lists every line with +, - or two spaces (no context trimming), and word or character mode shows one merged text with removals struck through and additions highlighted. There’s no side-by-side view.
What diffs can’t see
- Renames. A diff between two files only knows about those two files. If you renamed a file and made small edits, a file-level diff sees a wholesale delete and a wholesale insert. Git’s diff layer adds rename detection (
-Mflag) that compares similarity scores between deleted and added files; standalone diff tools usually don’t. - Block moves. Move a function from line 50 to line 200 of the same file and the diff shows a delete at 50 and an insert at 200. To recognize this as “the same code, relocated” requires post-processing —
git diff --color-moveddoes this, plaindiffdoes not. - Semantic equivalence. Reformatting (changing indentation, reordering object keys, normalizing whitespace) shows up as changes even when behavior is identical. JSON-aware diff tools like
jdor YAML-aware ones operate on parsed structure rather than raw text. For raw JSON specifically, see JSON diff. - Three-way merge. Two-way diff says what changed; it doesn’t tell you how to combine two divergent edits of a common ancestor. That’s a merge tool, not a diff tool.
Whitespace handling
Whitespace differences are real changes — and noisy ones. Most diff tools provide flags to ignore them:
- Ignore trailing whitespace — common default. End-of-line spaces are rarely meaningful.
- Ignore all whitespace — use carefully.
if(x)andif ( x )are equivalent in most languages but not all (Python whitespace is significant; Make depends on tabs). - Ignore line ending differences —
\r\nvs\n. Common when files cross between Windows and Unix.
The tool above compares text exactly — it has no ignore-whitespace option, so strip trailing spaces or normalise line endings first if they aren’t the change you’re looking for.
Common pitfalls
- Diffing minified files. Minifiers strip whitespace and rename variables; the line-level diff is one giant change. Pretty-print or beautify before diffing — see JSON formatter, HTML formatter, CSS formatter.
- Diffing files with different line endings. A diff that shows every line as changed when the visible text is the same is almost always a
\r\nvs\nissue. Normalize first. - Diffing across encodings. UTF-8 vs UTF-16 vs Latin-1 looks like a total change at the byte level. Decode to a common encoding first.
- Reading the wrong direction. Diff tools have a convention —
-is the first input,+is the second. Some tools use the reverse. If a diff looks backwards, check which input is which.
For structured-data diffs that ignore reformatting, see JSON diff.