Markdown Diff: Compare Files and Write Diff Blocks
September 11, 2026 · 9 min read
Markdown Diff: Compare Two Markdown Files and Write Diff Blocks
A markdown diff means one of two things. It's either a fenced code block tagged diff that colors added and removed lines, or a comparison of two .md files to see what changed. This guide covers both, with the block syntax first and a CLI, GitHub, and online workflow for comparing files second.
Markdown Diff Syntax for Code Blocks
The diff block is an ordinary fenced code block whose info string is diff. Inside it, every line starts with one of a few markers, and the renderer colors the line by that marker:
| First character | Meaning | Typical color |
|---|---|---|
+ | Added line | Green |
- | Removed line | Red |
| Space | Unchanged context line | Plain |
@@ | Hunk header from a real patch | Muted or blue |
! | Changed line (rare, from old diff formats) | Varies |
Here's a diff block that shows a README edit:
- Run `npm install` to install dependencies.
+ Run `npm ci` to install dependencies from the lockfile.
Then start the dev server:
+ npm run dev
GitHub renders the first line with a red background, the second and fourth with green, and the third as plain text. The markers stay visible in the output, which is what makes the block readable in a plain-text terminal as well.
Two details trip people up. The character after the marker is part of the content, so -Run and - Run both work, but keep them consistent. The fence can use three backticks or three tildes. The CommonMark spec says the first word of the info string names the language, and diff is the word every highlighter recognises.
What Do Three Backticks Mean in a Markdown Diff Block?
The three backticks open and close a fenced code block. Nothing between them is parsed as Markdown, so a line that starts with - is a removed line, not a bullet. That's the whole reason diff blocks work: the fence switches the parser off and the diff label switches a syntax highlighter on.
GitHub's highlighter, Linguist, lists diff as a language with the aliases udiff and the file extensions .diff and .patch. Any of those spellings after the fence produces the same coloring. The languages.yml file in the Linguist repo is the source of truth for the list.
One limitation you can't work around: a fence takes one language. Write ```diff and you lose C# or Python coloring inside the block. GitHub picks the grammar from the info string and applies exactly one. If you want both, the closest option is a plain language block plus a comment such as // changed on the lines you edited.
Try a Markdown Diff Block in the Editor
Paste or edit the sample below. The preview here shows the block as monospace text with the markers visible, the way Slack does. Use it to check the fence syntax, then paste the same block into a GitHub comment or README to see the green and red coloring. The sample uses tilde fences, which are valid CommonMark and handy when your Markdown itself contains backticks.
Where Do Diff Blocks Render in Color?
Support is wide because diff is in almost every highlighter's default set. These are the behaviours described in each platform's documentation.
GitHub and GitLab both color + and - lines in READMEs, issues, pull request comments, and wiki pages. The GitHub Markdown cheat sheet covers the rest of GFM fenced-block syntax.
VS Code highlights diff blocks in its Markdown preview through its bundled highlighter. The code --diff a.md b.md command also opens two files side by side, which is a different feature covered below.
Obsidian highlights code in reading view with Prism, whose default bundle includes the diff grammar, so + and - lines get their colors there too.
Discord applies the same colors in its code blocks, which is why the diff trick appears in so many Discord formatting guides. Slack does not highlight code blocks by language, so a diff block there shows as monospace text with the markers visible.
How Can I Compare .md Files?
The second meaning of markdown diff is comparing two versions of a file. The tools you already have do it well, as long as you diff by word rather than by line.
Line diff with the diff command
The classic unified diff works on any two files:
diff -u draft-v1.md draft-v2.md
The output is itself a diff, so you can paste it into a ```diff block in a pull request comment or a changelog. The catch is that prose changes look noisy. Change one word in a hard-wrapped paragraph and the whole line is reported as removed and re-added.
Word diff with git
Git compares two files that aren't in a repository when you pass --no-index, and --word-diff reports changes at the word level. According to the git diff manual, the plain mode wraps removed words in [- -] and added words in {+ +}, and --word-diff=color uses colors only:
git diff --no-index --word-diff draft-v1.md draft-v2.md
git diff --no-index --color-words draft-v1.md draft-v2.md
For Markdown prose, --word-diff-regex is worth setting. The default splits on whitespace, so a moved comma shows as a whole-word change. Setting --word-diff-regex='[^[:space:]]+|[[:punct:]]' treats punctuation as its own token, which makes small edits report as small edits.
Write one sentence per line
We prefer a writing habit over a tool here: put each sentence on its own line. Markdown joins consecutive lines into one paragraph, so the rendered output is identical, but every diff tool now reports changes per sentence. The line break guide explains why a single newline doesn't create a break, which is the property this trick relies on.
Online compare tools
Online compare tools take two pasted texts and highlight the differences, usually with a side-by-side layout and a word-level mode. They work on the Markdown source, not on the rendered page, so a change from *italic* to _italic_ counts as a change even though it renders the same. Check the privacy note on any such tool before pasting private drafts.
Compare in VS Code
VS Code handles the same comparison locally. Select two files in the Explorer, right-click, and choose Compare Selected, or run:
code --diff draft-v1.md draft-v2.md
To see what a change looks like once rendered, paste each version into the editor in turn, or convert both with the Markdown to HTML tool and diff the HTML. That second route catches rendering differences the source diff hides, such as a list that stopped being a list because of an indentation change.
GitHub Rich Diff and GitLab Merge Request Diffs
When a pull request changes a .md file, GitHub offers two views. The source view is the normal line-by-line diff. The rich diff shows the rendered document with changed passages highlighted, and you switch with the file icon labelled "Display the rich diff" at the top of each file.
GitHub's prose rendering docs list the supported formats: Markdown, AsciiDoc, Textile, ReStructuredText, Rdoc, Org, Creole, MediaWiki, and Pod. The same page notes the limits. Review comments attach to lines in the source view only, some embedded content can't render, and very large changes may fall back to source. Reviewing a README rewrite is easier in rich view and commenting on it is easier in source, so most reviewers flip between the two.
GitLab's merge request changes page gives you inline or side-by-side layouts, a whitespace toggle, and expandable context, but GitLab's changes documentation doesn't describe a rendered view for Markdown. If you need a visual comparison there, render both versions and compare them by eye, or use the rich view on a GitHub mirror.
Common Markdown Diff Mistakes
Expecting two languages in one fence. ```diff csharp doesn't give you C# colors plus diff colors. GitHub reads the first word and ignores the rest. Pick the one that matters for the reader.
Forgetting the marker on context lines. Inside a diff block, a line with no leading space is still plain, but tools that parse the block as a real patch expect the single space. Indent context lines by one space and the block works as both documentation and input to git apply.
Diffing hard-wrapped prose by line. If your editor wraps at 80 columns, a one-word edit re-flows the paragraph and the diff reports every line as changed. Use --word-diff or switch to one sentence per line.
Markdown Diff FAQ
Whether you need a markdown diff block in a changelog or a real comparison of two drafts, the tools are simple: a diff fence for display, git diff --word-diff for prose, and GitHub's rich diff for reviewing rendered pages. Draft the diff block in the editor to check the fence syntax, then paste it into GitHub to see the coloring. Keep sentences on their own lines so your next comparison stays readable.