Diff and Patch Viewer

Paste the output of git diff, git format-patch or diff -u to read it as a colour-coded side-by-side view, with per-file statistics and a check that every hunk is complete.

Input

Settings

History

Load from URL

Reading unified diffs

The unified diff is the patch format behind git diff, pull request downloads, .patch files attached to bug reports and diff -u output. Each changed file starts with --- and +++ lines naming the old and new versions, and each block of changes, a hunk, begins with a header like @@ -10,6 +10,7 @@: starting at line 10, six lines of the old file become seven in the new one. Inside a hunk every line starts with a space (unchanged context), - (removed) or + (added). Git adds its own extended headers before the file names, such as index, new file mode, rename from and rename to.

That plain-text form is precise but tiring to read once a change touches several files. This viewer renders it with diff2html, highlighting the words that changed within a modified line, not just the line as a whole.

How to view a patch

Paste the diff, or open a .diff or .patch file, and switch to the Preview tab. The code pane keeps your text exactly as pasted, since a single changed space can stop a patch from applying; only Windows line endings are normalised. The info panel totals Files changed, Insertions and Deletions, and adds counts of files added, deleted, renamed or binary when there are any. With more than one file, the preview starts with a file list you can jump through.

Preview layout chooses how the preview is drawn:

  • Side by side puts the old file on the left and the new file on the right, aligned line for line. It suits review on a wide screen.
  • Line by line interleaves removed and added lines in a single column, like a terminal, which works better on a laptop or phone and for long lines.

Patches often contain unreleased code or configuration. The rendering is done in your browser tab, so the diff stays on your machine. Ctrl/Cmd+Shift+C copies the normalised text.

Validation: when a patch will not apply

git apply and patch trust the numbers in each @@ header. If a hunk claims 7 lines but the text has 5, the tools fail with “corrupt patch” or apply the wrong lines. The viewer counts the context, removed and added lines of every hunk and compares them with the header:

  • Too few lines at the very end of the input is a warning that the diff looks truncated, the usual result of copying from a terminal that cut off the last lines.
  • Too few lines followed by another hunk, or more lines than declared, is an error, since the patch is internally inconsistent.
  • A line inside a hunk that does not start with a space, +, - or \ is reported. Editors that strip trailing whitespace sometimes remove the leading space from blank context lines, which corrupts patches in exactly this way.

Malformed @@ headers are flagged too, and \ No newline at end of file markers are understood and not counted as content.

Input that is accepted

Git diffs with diff --git headers, plain diff -u output with timestamps after the file names, Subversion’s Index: style and bare hunks without file headers all work. Renames, copies, mode changes and Binary files ... differ lines are recognised. A paste that has no diff --git, ---/+++ or @@ line at all is rejected outright, because there is nothing to render.

Examples

One hunk from git diff

Six old lines become seven new ones, matching the hunk header, so the diff validates cleanly with 2 insertions and 1 deletion.

Input
diff --git a/src/cart.ts b/src/cart.ts
index 4c1e2a0..9b7d311 100644
--- a/src/cart.ts
+++ b/src/cart.ts
@@ -10,6 +10,7 @@ export class Cart {
   add(sku: string, qty = 1) {
     const line = this.lines.get(sku) ?? { qty: 0 };
-    line.qty += qty;
+    if (qty <= 0) throw new RangeError('qty must be positive');
+    line.qty += qty;
     this.lines.set(sku, line);
     return this;
   }
Output
diff --git a/src/cart.ts b/src/cart.ts
index 4c1e2a0..9b7d311 100644
--- a/src/cart.ts
+++ b/src/cart.ts
@@ -10,6 +10,7 @@ export class Cart {
   add(sku: string, qty = 1) {
     const line = this.lines.get(sku) ?? { qty: 0 };
-    line.qty += qty;
+    if (qty <= 0) throw new RangeError('qty must be positive');
+    line.qty += qty;
     this.lines.set(sku, line);
     return this;
   }
Open this example in the tool

Rename plus a new file, line by line

The info panel counts one rename and one added file, and the single-column layout keeps both files readable on a narrow screen.

Input
diff --git a/README.md b/docs/README.md
similarity index 90%
rename from README.md
rename to docs/README.md
index 1a2b3c4..5d6e7f8 100644
--- a/README.md
+++ b/docs/README.md
@@ -1,3 +1,3 @@
 # Orders service
-Run `npm start` to boot the API.
+Run `npm run dev` to boot the API with hot reload.
 See docs/deploy.md for production.
diff --git a/config/flags.json b/config/flags.json
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/config/flags.json
@@ -0,0 +1,3 @@
+{
+  "newCheckout": true
+}
Output
diff --git a/README.md b/docs/README.md
similarity index 90%
rename from README.md
rename to docs/README.md
index 1a2b3c4..5d6e7f8 100644
--- a/README.md
+++ b/docs/README.md
@@ -1,3 +1,3 @@
 # Orders service
-Run `npm start` to boot the API.
+Run `npm run dev` to boot the API with hot reload.
 See docs/deploy.md for production.
diff --git a/config/flags.json b/config/flags.json
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/config/flags.json
@@ -0,0 +1,3 @@
+{
+  "newCheckout": true
+}
Open this example in the tool

Plain diff -u of a config file

Output from diff -u without git headers works too; the timestamps after the file names are ignored.

Input
--- nginx.conf.orig	2026-09-14 08:21:05
+++ nginx.conf	2026-09-14 08:25:40
@@ -3,4 +3,4 @@
 server {
     listen 80;
-    server_name example.com;
+    server_name example.com www.example.com;
     root /var/www/html;
Output
--- nginx.conf.orig	2026-09-14 08:21:05
+++ nginx.conf	2026-09-14 08:25:40
@@ -3,4 +3,4 @@
 server {
     listen 80;
-    server_name example.com;
+    server_name example.com www.example.com;
     root /var/www/html;
Open this example in the tool

Common errors and how to fix them

ErrorCauseFix
This does not look like a unified diff: no "diff --git", "---/+++" or "@@" hunk lines were foundThe input is a copy of a whole file, two versions pasted one after the other, or ordinary text rather than a unified diff.Generate a unified diff with git diff, git format-patch or diff -u old new and paste that output.
Hunk "@@ -1,7 +1,8 @@" declares 7 old and 8 new lines, but the hunk has 5 old and 7 new lines; the diff looks truncatedThe last hunk ends before its header says it should, usually because trailing context lines were not copied.Copy the diff again in full, or correct the counts in the @@ header so they match the lines present.
Line 5 is inside a hunk but does not start with ' ', '+', '-' or '\'A context line lost its leading space, typically when an editor trimmed whitespace or the diff was pasted through a chat app.Restore the single leading space on unchanged lines, including blank ones, or regenerate the patch.
Malformed hunk header; expected "@@ -start,count +start,count @@"A line begins with @@ but the numbers are missing or garbled, often after hand-editing a patch.Rewrite the header in the @@ -10,6 +10,7 @@ form, with the start line and line count for each side.

Frequently asked questions

How do I view a git diff side by side?

Paste the output of git diff and open the Preview tab with Preview layout set to Side by side. The old version appears on the left and the new one on the right.

Can I open a .patch file from GitHub?

Yes. Adding .patch or .diff to a GitHub pull request or commit URL gives a unified diff; save it and open it here, or paste its contents.

Why does the viewer say my diff looks truncated?

The last hunk has fewer lines than its @@ header promises. git apply would reject the patch, so copy the complete output again.

Does the viewer change my diff?

No. The text is kept byte for byte except that CRLF line endings become LF. Whitespace inside a patch is significant, so nothing else is reformatted.

Related tools