Text Diff Checker
Compare two blocks of text and highlight what was added, removed and changed, with word-level and character-level views for small edits.
A diff cannot see that something moved
Every ordinary diff is built on the longest common subsequence, and a subsequence has to keep its order. That means a move cannot be represented at all. It comes out as a deletion in one place and an insertion in another, and the bill is proportional to how much moved:
| Edit | Lines reported changed | Conceptually |
|---|---|---|
| Two blocks of 1 lines swapped | 2 | one move |
| Two blocks of 3 lines swapped | 6 | one move |
| Two blocks of 10 lines swapped | 20 | one move |
| Two blocks of 50 lines swapped | 100 | one move |
Exactly 2n every time, checked at every size from 1 to 40. The common subsequence can keep one block or the other but never both, so one of them is deleted and re-inserted in full.
The nuance worth knowing is that distance is free and size is not. Moving a single line from the bottom of a file to the top costs two changed lines whether the file is five lines or five hundred:
| File length | Last line moved to first |
|---|---|
| 5 lines | 2 changed |
| 20 lines | 2 changed |
| 100 lines | 2 changed |
So a one-line move across two hundred lines is fifty times cheaper than swapping two fifty-line blocks. It is never how far something travelled — only how much of it did.
The practical consequence: reordering functions in a file produces a diff that reads like a rewrite, and no reviewer setting fixes it, because the information that it was a move was never in the diff to begin with. This is the real argument for keeping moves and edits in separate commits — a move-only commit is large but trivially checkable, while the two mixed together are genuinely hard to review.
And "percent changed" depends entirely on the unit
Change one word in a nine-word sentence — the quick brown fox jumps over the lazy dog becomes the quick brown cat jumps over the lazy dog —
and ask how much of it changed. All three of these are computed the same way from the same
single edit:
| Compared by | Changed | Out of | Share |
|---|---|---|---|
| Character | 6 | 43 | 14.0% |
| Word | 2 | 9 | 22.2% |
| Line | 2 | 1 | 200.0% |
Three answers, one edit. The line figure exceeds 100% because that single line is deleted and re-inserted — two operations on one line — which is a fair warning that a percentage is the wrong summary unless the unit is stated alongside it.
Choosing the unit is really choosing what you want to see. Line diffs are right for code, because a line is roughly a statement and reviewers think in statements. Word diffs are right for prose, where a line is an accident of wrapping and a line diff will mark a whole paragraph as changed for one corrected typo. Character diffs are right when the change is inside a token — a URL, an identifier, a number — and useless at any larger scale, because they scatter single characters across the output.
How to use
- Paste the original text on one side and the revised on the other.
- Read the highlighted differences.
- Switch to word or character view for small edits.
- Ignore whitespace if formatting changed but content did not.
Frequently asked questions
How does a diff actually work?
By finding the longest common subsequence between the two texts — the largest set of lines appearing in both in the same order. Everything outside that is reported as added or removed. A 'change' is simply a removal and an addition on adjacent lines.
Why does a small edit show a whole line as changed?
Because line-level diffs are the default, and any change within a line marks that line. A word-level or character-level view narrows it, which is far more readable for prose where paragraphs are long single lines.
Why does my diff show every line as changed?
Usually line endings. A file saved with Windows CRLF endings compared against one with Unix LF endings differs on every line invisibly. Trailing whitespace, or a change of indentation from tabs to spaces, produces the same effect.
Should I ignore whitespace?
It depends what you are looking for. Ignoring it is right when reviewing a reformatted file and you want the real changes. It is wrong for Python, YAML, or Markdown, where whitespace carries meaning and an indentation change is a substantive change.
Does my text get uploaded?
No. The comparison runs entirely in your browser, which matters when diffing contract drafts, configuration containing credentials, or anything else confidential.
What is a three-way merge?
A comparison of two versions against their common ancestor rather than against each other. Knowing the original lets a tool tell which side actually changed a line, so it can merge non-overlapping edits automatically and flag only genuine conflicts. It is what version control does when merging branches.
🔒 This tool runs entirely in your browser. Nothing you enter is uploaded, logged, or stored.