Layerbit

Text Diff Checker & Merge Tool

Compare two texts, code files, JSON documents, spreadsheets or whole zip folders; merge changes hunk by hunk; resolve three-way merges; apply and export unified patches. Every byte stays in your browser.

Original
Modified

Six comparisons, one page, nothing uploaded

Most diff sites do one thing: a line diff of two pasted texts. Real comparison work is messier than that — a merge that needs a third version, a JSON file whose keys were reordered, a spreadsheet export where one cell changed in ten thousand, a patch file someone emailed, two copies of a project folder. This page handles each of those with the right algorithm instead of forcing everything through a line diff.

Text & code

Line diff with word- or character-level highlights inside changed lines, syntax colouring for 14 languages, side-by-side or unified layout, context folding, and hunk-by-hunk merge: keep the original or accept the change for each block, then copy, download or send the merged text onward.

Three-way merge

Give it the base version and two edited copies and it merges them the way git merge does: non-overlapping changes from both sides are combined automatically, overlapping ones become conflicts you resolve with a click — ours, theirs or both.

JSON / YAML structure

Compares parsed values, not text. Key order, indentation and quoting style are ignored; what you get is a list of paths — $.config.timeout changed from 30 to 60, $.features[2] added — with arrays matched by position, as sets, or by an id field.

CSV / spreadsheet cells

Rows are matched by a key column you choose, so a re-sorted export does not show as "everything changed". The result is the list of rows added, removed, and changed, with the exact cells that differ. Excel files are read locally too.

Apply a patch

Paste a unified diff and the file it was made against; the patch is applied with context matching (and a fuzz fallback if line numbers drifted) and the result is shown as a diff so you can see exactly what it did before you trust it.

Folders (.zip)

Drop two zip archives — two releases, a backup and a live copy — and get the file-level picture: added, removed, identical, and modified files, each modified file one click from a full text diff. The archives are unpacked in memory in your browser.

Try it with a sample

Each sample switches to the right mode and runs. They are small enough to read in full, so you can check the output against your own expectation.

How the merge works

A diff is a list of hunks — contiguous blocks where the two sides disagree. The merged result starts as the modified text; above each hunk you choose Keep original to revert that block, Accept change to keep it, or Both to include the original lines followed by the modified ones. The merged text updates live, is editable, and can be sent to any other tool.

This is the same operation a code review tool performs when you "accept" or "reject" a suggestion, and the same one you do by hand when reconciling a config file someone edited on the server against the one in the repository. Doing it with explicit per-hunk decisions is faster and less error-prone than copy-pasting lines between two editors, and the exported .patch is a record of exactly what was changed.

Three-way merge, in one paragraph

With only two versions, a tool cannot know which side changed a line — it only knows the lines differ. With a third version, the common ancestor, it can: a line that differs from the base on one side and matches the base on the other was changed by that one side, and the change is taken. If both sides changed the same region differently, neither can be preferred automatically, and that is a conflict. The output uses the same <<<<<<< ours / ======= / >>>>>>> theirs markers as Git (plus the base in ||||||| diff3 style), so it drops straight into any editor that understands them — or resolve each conflict here with one click.

What a diff is actually computing

Comparing two blocks of text is not a character-by-character scan. A diff algorithm looks for the longest common subsequence — the largest set of lines appearing in both versions in the same order — and everything outside that becomes an addition or a deletion. That framing explains most of the behaviour people find surprising.

It is why moving a block of code often shows as a large deletion plus a large insertion rather than "moved": a line-based diff has no concept of movement, only of presence and position. And it is why inserting one line near the top can shift how everything below it aligns, if the algorithm finds a cheaper way to match the remaining text.

Invisible differences

The hardest diffs are the ones you cannot see: a trailing space, a tab where the rest of the file uses spaces, a non-breaking space pasted from a document, or a zero-width character from a web page. Turn on Show whitespace to render spaces and tabs visibly, and the Unicode Inspector for anything stranger.

Line endings

Windows uses CRLF, Unix LF. A file that has crossed platforms without normalisation differs on every line while looking unchanged. Line endings are normalised before comparing here, so that case shows as "no changes" rather than a wall of red.

Unicode that looks the same

A Cyrillic а renders identically to a Latin a. So do curly and straight quotes after a word processor has been involved. Normalisation form matters too: é can be one code point or e plus a combining accent, and the two are different strings.

Where a text diff is the right tool

Version control handles diffing committed code, so the useful cases for a standalone comparison are the ones outside a repository:

Why two files that look identical still differ

The most frustrating diff is the one that reports a change you cannot see. Almost always the difference is a character that renders as nothing, or as the same thing your editor renders something else as. Four causes account for nearly all of these.

Line endings. Windows terminates a line with CRLF (carriage return plus line feed), Unix and macOS with a bare LF. A file that has travelled through a Windows editor, a zip archive, or a checkout with Git's core.autocrlf enabled can differ from its counterpart on every single line while looking identical on screen. This tool ignores the difference by default; if a diff elsewhere marks an entire file as changed, check the line endings before you check anything else.

Trailing whitespace. A space or tab at the end of a line is invisible in most editors and significant to a byte-for-byte comparison. It is also the change most often introduced accidentally, because pressing space before a newline leaves no visual trace. Use the Trim trailing option to confirm that this is the only difference, then remove the whitespace rather than leaving the option on permanently — it will hide a real change eventually.

Unicode normalisation. The character é can be stored as a single code point (U+00E9) or as e followed by a combining acute accent (U+0065 U+0301). Both render identically in every font. They are different byte sequences, so they are a difference. macOS filesystems have historically preferred the decomposed form, which is why filenames with accents copied from a Mac can mismatch a list generated on Linux.

Invisible and look-alike characters. A zero-width space (U+200B), a non-breaking space (U+00A0) pasted from a web page or a word processor, a byte-order mark at the start of the file (U+FEFF), or a Cyrillic а standing in for a Latin a all produce a change with no visible cause. The BOM case is particularly common: it is three bytes prepended to a UTF-8 file by some Windows tools, and it breaks shebang lines, YAML documents and JSON parsers while remaining completely invisible in an editor.

When a difference refuses to explain itself, the fastest resolution is to stop looking at the rendered text and look at the bytes. cat -A file on Linux marks line endings with $ and tabs with ^I; xxd file | head shows you the raw hex, including a leading efbbbf BOM. Once you know which character it is, the fix is usually a single editor setting away.

Line diff, word diff, character diff

The same two inputs can produce three very different-looking comparisons depending on the granularity the algorithm works at, and choosing the wrong one is why a diff is sometimes unreadable.

Line granularity treats each line as one indivisible unit: a line either matches or it does not. This is what git diff and code review tools show by default, and it is the right default for source code, where a line is roughly a statement and changing part of a line means the whole line needs re-reading. Its weakness is prose. Reflow a paragraph so the words wrap differently and a line diff reports every line as changed even though only one word moved.

Word granularity splits on whitespace, so a reflowed paragraph shows only the words that actually changed. This is what you want for documentation, translated strings, legal text and anything else written to be read by people rather than parsed by a compiler. It is a poor fit for minified code or long identifiers, where a word can be hundreds of characters long.

Character granularity compares individual characters. It is the only mode that will show you that getUserId became getUserID, or that a single digit changed in a long hash. It is also the noisiest: on two genuinely different paragraphs it produces a mosaic of tiny insertions and deletions that is harder to read than seeing the old and new text side by side.

The practical rule is to start at line level to see the shape of the change, then narrow to word or character level on the specific lines that report a difference you cannot account for. This page does exactly that: changed lines are identified first, then the changed regions inside those lines are highlighted at the granularity you pick. That two-stage presentation is why a good diff is readable at all — you get the structure from the coarse pass and the detail from the fine one, without drowning in either.

Engineering FAQ

The engine first runs a line-level diff to find which lines changed. Where a block of removed lines is immediately followed by a block of added lines, it pairs them up and runs a second diff inside each pair at word or character granularity, highlighting only the parts that actually differ. Lines that were purely added or removed are shown whole.

They change how lines are compared, not how they are displayed. Ignore whitespace collapses every run of spaces and tabs to one space and trims the ends, so a reformatted file shows only logic changes. Ignore case compares lower-cased lines. Trim trailing ignores whitespace at the end of a line only. Ignore blank lines lets empty lines match anywhere. Line endings (CRLF vs LF) are always normalised. The original text is still shown in full in the result.

Run a text comparison, then use the controls above each change block: Keep original, Accept change, or Both. The Merged result pane below the diff updates as you decide, starting from the modified text with every change accepted. You can also edit the merged text directly, copy it, download it, send it to another tool, or load it back as the new original to continue from there.

When two people (or two branches) edited the same file independently and you have the version they both started from. A two-way diff cannot tell which side changed a line; with the base it can, so non-overlapping edits from both sides merge automatically and only genuine overlaps become conflicts. The output uses Git's conflict markers with diff3-style base sections, and each conflict can be resolved in place with ours, theirs, or both.

A structural diff parses both documents and compares the resulting values. Two JSON files with the same data but different key order, indentation or quoting show no difference, and the changes that do exist are reported by path, like $.server.port changed from 8080 to 443. Use it for configuration files, API responses and anything machine-generated. Use the text diff when formatting itself matters, such as reviewing a hand-edited file.

By a key column you choose from the header row, such as an id, SKU or email. Rows with the same key are compared cell by cell regardless of where they appear, so a re-sorted or filtered export shows only real changes. Rows whose key exists on one side only are reported as added or removed, and columns that appear or disappear are listed separately. If the file has no natural key, match by row order instead.

Yes. The export is a standard unified diff with --- and +++ headers and @@ hunk ranges, which git apply, patch -p0 and every code review tool accept. The Apply a patch mode reads the same format back, including patches produced by git diff, and uses context matching with a fuzz fallback when line numbers have drifted.

No. Files are read with the browser's FileReader, zip archives are unpacked with the browser's own DecompressionStream, and every algorithm on this page is JavaScript running in the tab. The privacy indicator in the header counts any network request the page makes; it stays at zero while you work. Closing the tab discards everything unless you chose to save a run to the local history.

Tens of thousands of lines compare in well under a second; the limit is rendering, not diffing. For files over about 20,000 lines, set Context to 3 or 5 lines so only the changed regions are rendered, and prefer word over character highlighting. The structural and table modes handle documents of several megabytes. Share links are capped at roughly 60 KB of compressed input; larger comparisons can be exported as a patch or HTML report instead.

Deployment Changelog