Diffing & Comparing Files Explained
How diffs work — line vs word diffs, the LCS/Myers algorithm, unified diff format, and why comparing JSON/YAML/CSV needs structural normalisation first.
Last updated: 26 July 2026
A diff (short for “difference”) is a compact description of what changed between two versions of some text or data — what was added, what was removed, and what stayed the same. Diffs power code review, version control, config auditing and data reconciliation. Understanding how they work helps you read them faster and pick the right kind of comparison for the job.
What a diff actually computes
Given an “old” and a “new” version, a diff finds the smallest set of edits that turns one into the other. To do that, it first works out which parts are unchanged — the largest chunk common to both sides — and treats everything else as either an insertion or a deletion.
Diffs come in different granularities:
- Line-based — each line is compared as an indivisible unit. Change one character and the whole line reads as removed-then-added. This is what
git diffshows by default and is ideal for source code. - Word- or character-based — the comparison looks inside lines and highlights only the tokens that actually changed. This is far more readable for prose, long lines, or minified content.
The idea behind the algorithm: LCS
Most diff tools are built on the Longest Common Subsequence (LCS). A subsequence keeps items in order but may skip some — so the LCS of two files is the longest ordered set of lines (or characters) that appears in both. Whatever is not in the LCS is exactly what changed: items present only in the old version are deletions, and items present only in the new version are insertions.
For example, the LCS of A B C D and A X C D is A C D. Everything else (B removed, X added) is the diff.
The classic Myers diff algorithm (Eugene Myers, 1986) is the efficient way to find this. Rather than exhaustively comparing everything, it searches for the shortest edit script — the fewest insertions and deletions — by finding the longest common subsequence quickly. Git, Mercurial and most editors use Myers (or a close variant) under the hood. You don’t need the maths to use a diff, but the key intuition is simple: the tool keeps the biggest common part and reports the rest as changes.
Unified diff format
The most common way to display a diff is the unified format, the same one git diff and patches use:
@@ -1,4 +1,4 @@
name: web
-replicas: 2
+replicas: 3
image: nginx
-port: 80
+port: 8080
Reading it:
- Lines starting with
-were removed from the old version. - Lines starting with
+were added in the new version. - Lines with a leading space are context — unchanged, shown so you can see where the change lives.
- The
@@ -1,4 +1,4 @@line is a hunk header: it says this hunk starts at line 1 and spans 4 lines in the old file (-1,4) and line 1 spanning 4 lines in the new file (+1,4).
A file’s diff is a series of these hunks, each covering one region of change with a little surrounding context.
Text diff vs structural (semantic) diff
A plain text diff compares bytes and lines. That is perfect for code, but it produces misleading noise for data formats like JSON, YAML and CSV, because those formats allow the same data to be written many different ways:
- Object keys in a different order (
{"a":1,"b":2}vs{"b":2,"a":1}) - Different indentation or whitespace
- Trailing commas, quoting style, or a trailing newline
- Numbers written as
1.0vs1
A line diff flags all of these as differences even though nothing meaningful changed. A structural (semantic) diff avoids this by normalising first:
- Parse each side into its data model (objects, arrays, values).
- Re-serialise both with identical formatting.
- Sort keys (and, where order is irrelevant, sort arrays or rows) so ordering differences vanish.
- Then compare the normalised results.
After normalisation, only genuine value changes remain — a key added, a value edited, an element removed. This is what you want when reconciling two config files or two API responses.
Common uses
- Code review — see exactly what a change touches before merging; line diffs with word-level highlighting.
- Config drift — compare the config that’s running against the config that’s checked in; structural diff so key-order and formatting don’t create false alarms.
- Data reconciliation — compare two exports (CSV/JSON) to find added, removed or changed records.
- API response comparison — diff yesterday’s response against today’s, or staging against production, to detect unexpected changes; normalise first so field ordering is ignored.
Tips for cleaner diffs
- Normalise line endings — convert
\r\n(Windows) and\n(Unix) to one style before comparing, or entire files show as changed for an invisible reason. - Sort when order is irrelevant — sort object keys always, and sort arrays/rows only when their order carries no meaning.
- Ignore whitespace when appropriate — hide indentation and trailing-space changes to focus on substance, but keep whitespace significant for Python, YAML and Markdown.
- Diff at the right granularity — line diff for code, word/character diff for prose, structural diff for data.
- Trim the noise — strip trailing newlines and BOMs, and pick a consistent number formatting, so cosmetic differences don’t drown the real ones.
Text diff vs structural diff at a glance
| Aspect | Text diff | Structural diff |
|---|---|---|
| Compares | Raw lines / characters | Parsed data model |
| Key / field re-ordering | Shows as a change | Ignored (keys sorted) |
| Whitespace & indentation | Shows as a change | Ignored (re-serialised) |
| Formatting (quotes, trailing commas) | Shows as a change | Ignored |
| Real value edits | Caught | Caught |
| Invalid / malformed input | Still diffs it | Fails to parse — must be valid first |
| Best for | Code, prose, plain text | JSON, YAML, CSV, config, API responses |
The short version: a text diff catches everything including cosmetic noise; a structural diff catches only meaningful data changes but needs parseable input.
Work with diffs in your browser
Every CodingSetu diff and compare tool runs entirely client-side — your files are never uploaded. Compare plain text, code, JSON, YAML and CSV, with line, word and structural modes.
References
- The Myers diff algorithm — a readable explainer — walks through Myers’ 1986 shortest-edit-script paper step by step.
- Wikipedia: diff — history, unified format and variants.
- Wikipedia: Longest common subsequence — the problem underlying most diff algorithms.
- git diff documentation — options for whitespace handling, word diffs and output format.
Try it: open the diff tools to compare text, JSON, YAML and CSV right in your browser.
Frequently asked questions
Why do my JSON files show as different when the data is the same?
A plain text diff compares characters and lines, so re-ordered keys, extra whitespace, different indentation, or trailing commas all look like changes even when the underlying data is identical. Use a structural (semantic) diff that parses both sides, sorts keys and re-serialises them, so only real value changes are reported.
What is the difference between a line diff and a word diff?
A line diff treats each whole line as a unit — if one character changes, the entire line is marked removed and re-added. A word or character diff looks inside the line and highlights only the exact tokens that changed. Line diffs are great for code; word/character diffs are better for prose or long lines.
Does the order of keys or rows matter when comparing?
For plain text diffs, yes — re-ordering lines or keys shows up as differences. For structural comparison it depends on the format. JSON and YAML objects are unordered, so keys should be sorted before comparing. Arrays and CSV rows are ordered by default, so sort them yourself only when the order genuinely does not matter.
Should I ignore whitespace when diffing?
Often, yes. Ignoring trailing whitespace, indentation and blank-line changes removes noise from reformatting so you see the substantive edits. But keep whitespace significant for whitespace-sensitive formats like Python, YAML, Makefiles or Markdown, where indentation changes meaning.
Is my data uploaded when I use the diff tools?
No. Every CodingSetu diff and compare tool runs entirely in your browser. Your files never leave your device and are never sent to a server.