Text Diff

Compare two texts and see added, removed, and changed lines

Enter both texts and press Compare.

About Text Diff

This tool splits both texts into lines and compares them with a longest-common-subsequence (LCS) algorithm: it keeps as many lines in common as possible, marks lines only on the left as removed (-), and lines only on the right as added (+). It does not highlight which characters changed inside a line.

If you have ever looked at a diff and thought "that's not what I changed", you have met the central fact about diff algorithms: they find the shortest description of the difference, not the edit you actually made. This page explains how that works and how to get results that are easier to read.

A short history of diff

Computing a diff is the same problem as finding the shortest list of insertions and deletions that turns text A into text B. The original Unix diff (1976) used the Hunt–McIlroy algorithm. In 1986 Eugene Myers published "An O(ND) Difference Algorithm and Its Variations" in Algorithmica, where N is the combined length of both inputs and D is the size of the minimal edit script. Because the running time depends on D, the algorithm is fast when two files are mostly the same, which is the normal case. Myers' algorithm is still Git's default.

This tool uses Myers' algorithm too, in its linear-space form that splits the problem in half around a "middle snake". Memory grows with the number of lines, not with their product, and two 20,000-line files that differ in 1% of lines compare in well under a second. Inputs that differ almost everywhere still take time proportional to the difference, so tens of thousands of completely different lines can take a few seconds. The number of changes is always the minimum, but when several minimal answers exist it may pick a different one from Git. Inside a changed block, deletions are listed first.

Why diffs look wrong

The classic case is code. Add a new function right above a similar existing one, and the diff may claim you inserted the end of the new function plus the beginning of the old one, pairing the closing braces the "wrong" way. Nothing is broken: several edit scripts have the same length and the algorithm picked one. Git offers --diff-algorithm=patience and histogram for this reason. Patience diff first anchors on lines that appear exactly once in each file, such as function signatures, and then diffs the gaps, which usually matches human intent better.

Diff has no concept of "moved". Swap two paragraphs and you get one deletion and one insertion. Some tools add move detection on top (Git's --color-moved, for instance), but the underlying algorithm never sees a move.

Change one letter in a line and the whole line shows as removed and re-added. That is the difference between line diff and word or character diff. Line diff is right for code and configuration files, where a line is a meaningful unit. For prose, where a paragraph is often a single long line, it is nearly useless: every edit replaces the whole paragraph. Putting one sentence per line before comparing (a habit some technical writers adopt for exactly this reason) makes a line diff readable.

Differences you can't see

Two lines that look identical but are reported as different almost always contain an invisible character. The no-break space (U+00A0) is common in text copied from web pages, Word or PDFs. Trailing spaces are another. The "ignore leading/trailing whitespace" option trims both ends of each line before comparing, and JavaScript's trim treats U+00A0 as whitespace, so a stray no-break space at the end of a line is ignored. One in the middle of a line is not.

Line endings are normalized before comparison: Windows CRLF, old Mac CR, and Unix LF are all treated as the same break. If Git says every line of a file changed but this tool says the files are identical, line endings are the likely cause (check your core.autocrlf setting or .gitattributes).

  • Ignore case: lines are lowercased for comparison only; the display keeps the original text.
  • Ignore empty lines: blank or whitespace-only lines are removed from both sides first; line numbers still refer to the original positions.
  • A trailing newline at the end of one text shows up as one added empty line.

Worked examples

Edited a block and added a new one

Input
Left: if (a) { x(); } Right: if (a) { y(); } if (b) { x(); }
Output
if (a) { + y(); + } + if (b) { x(); } (3 added, 0 removed, 3 unchanged)

You changed x() to y() and added a block, which is 1 deletion plus 4 insertions. The algorithm found a 3-line explanation: insert three lines in the middle. Shorter, and not what you did.

Looks the same, reported different

Input
Left: a[NBSP]b Right: a b
Output
- a b + a b (1 added, 1 removed)

The spaces are U+00A0 and U+0020. The whitespace option only trims line ends, so this stays a difference.

Windows vs Unix line endings

Input
Left: line1\r\nline2 Right: line1\nline2
Output
line1 line2 (2 unchanged)

Line endings are normalized first, so these compare equal.

How to use it

  1. Paste the original on the left and the revised text on the right.
  2. Turn on ignore case, whitespace or empty lines if those differences don't matter.
  3. Read the green (added) and red (removed) lines, and copy the result if needed.

Frequently asked questions

Why is the whole line marked when I changed one word?

The comparison unit is the line. For prose, split sentences onto separate lines before comparing.

Why does Git show a different diff for the same files?

Several minimal diffs can exist and different implementations choose differently. Git also treats CRLF and LF as different by default, while this tool does not.

Can I apply the copied output with patch or git apply?

Yes. "Copy unified diff" produces a standard patch with file headers (--- a/text.txt, +++ b/text.txt), @@ -start,count +start,count @@ hunk headers and three lines of context, so patch -p1 or git apply can apply it to the original file. Rename the file headers to your real file name. To make sure it applies exactly, the patch compares the texts character for character, regardless of the ignore-case, whitespace and empty-line options.

Is there a size limit?

No hard limit. Memory grows linearly with the number of lines, so tens of thousands of lines are fine. Similar files compare quickly; files that differ on almost every line can take a few seconds at that size.

Sources

Last reviewed:

Privacy and how data is handled