Git Diff Tools in 2026: OmniDiff, Difftastic, and Delta Compared

git diff is the one tool no developer escapes, and after twenty-one years it still makes the same deal: it diffs lines. Line in, line out, hunk headers, pager, done. That deal is why patches still apply and CI still works, and it is also why a pure reformat reads as a whole-file rewrite, a function that moved reads as deleted plus inserted, and every non-text file in your repo earns a one-line shrug ("Binary files differ").

A quietly useful ecosystem has grown around replacing parts of that deal, and one of the newest entries is also the most ambitious: OmniDiff (github.com/ivankovic/omnidiff), a Rust TUI that does not stop at reading syntax the way difftastic does, but reads pictures, fonts, archives, PDFs, and message catalogs by what they hold. This post is a ground-level tour of what each tool actually changes, the numbers its developers publish, and where each one belongs. The verdict up front: these are not really competitors. They are three different answers to one question, "what is wrong with git diff?"

The short version

  • git diff stays load-bearing. It produces patches. Everything below is for humans reading changes, not for git apply, git am, or CI.
  • delta solves presentation. It makes every diff git already produces readable: syntax themes, side-by-side view, hunk navigation. It earned a permanent seat in my .gitconfig during a year of living with modern replacements.
  • difftastic solves syntax. A structural diff over 30+ languages, MIT licensed, long-maintained, with honest limits spelled out in its own README.
  • OmniDiff solves content beyond code. Structural code diffing plus content-aware diffing of pictures, archives, fonts, cursors, PDFs, and message catalogs, with the boldest published metrics of the three, and unusually frank concessions about the targets it has not hit yet.
  • Mergiraf, diffsitter, and hunk sit at the edges. Mergiraf does syntax-aware merging while you rebase, diffsitter is a lighter tree-sitter differ, and hunk is a review-first terminal viewer for sprawling multi-file changes.

What git diff actually promises

Line-based diffing exists for good reasons. git diff's output is a patch: a format with its own grammar that git apply, code review platforms, and a decade of automation depend on. What git does offer is seams for the *reading* side: core.pager for the pager, git difftool for a per-file viewer, diff.external or GITEXTERNALDIFF for a full replace of the diff program itself. Each tool below reaches git through one or more of those seams, and Mergiraf skips them altogether, because a merge driver is a different kind of hook, not a reading seam. Worth remembering when someone calls a new tool "a git diff replacement". Nothing replaces the patch producer.

What the stock pipeline gives you only in cruder forms, or not at all:

  1. Syntax awareness. A brace rewrap shows as a change to the brace, not to nothing.
  2. Semantic pairing. A function that moved is rendered as deleted here, inserted there.
  3. Non-text content. PNG, WOFF2, PDF, .mo: "Binary files differ", full stop.
  4. A pleasant reading experience. That is what a pager is for, and vanilla git diff barely styles anything.

To be fair, stock git is not silent: -w and --word-diff can hide a reformat, --color-moved colors moved blocks, textconv drivers can decode some binaries into text, and hunk headers can name the enclosing function. These are heuristics layered on top of the line model, though, and delta is the tool that styles that output best (it advertises --color-moved support explicitly). OmniDiff and difftastic replace the model instead of decorating it.

OmniDiff: content-aware diffing, and a rename along the way

OmniDiff's timeline tells you how fast this project moves. v0.1.0, the first release the author calls ready for daily use as a git difftool, shipped in late September 2026. v0.2.0 (October 2026) brought the rename from CodeDiff, the project's name up to v0.1.1; the changelog's entire explanation is that the old name was a registered trademark, so the crate, the package names, and the config paths all moved. v0.3.0 landed on November 1, 2026, and the changelog reads like a team two engineers wide: code embedded in strings is now parsed in its own language, CSS class lists are diffed class by class, and average diff time dropped another twenty-something percent. The README is candid about how that pace is possible: development uses substantial AI assistance, currently Claude Code, and contributions are not accepted at this time.

The unusual part is how the project talks about its own claims. It publishes the metrics against the named machine and corpus, dates included:

  • Robust. Over 442,530 real before/after code pairs sampled from about 7,500 open-source repositories, 99.95% completed. The failures are documented file by file: generated code, parser tables, minified bundles, one 40,000-line single-header C++ library.
  • Content-aware. Across 2,018,010 changed files sampled the same way, 98.8% were diffed as text or as their actual content type rather than as opaque bytes.
  • Fast, at least for code. See the block below. The stated goals, a median at or under 100ms and a 99th percentile at or under one second, are both met over the author's 2,302-fixture code corpus. Non-code content runs closer to the line: 96% of pictures and 95% of fonts finish under 100ms, but only 88% of archives do, and archives miss the 99th-percentile goal outright (the slowest hold thousands of changed members). PDFs meet both goals, yet only 57% of them finish under 100ms, because every changed page gets drawn.
  • Accurate, and not yet at its own bar. This is the part I respect most. The project wants zero mismatched bytes on 90% of test cases against hand-painted ground truth, and at least 99% within 1%, and it says plainly that neither is met yet. On the zero-mismatch goal it reports 60.0% under the --full preset and 69.6% under --minimal; on the within-1% goal, 87.5% and 91.5%. The whole-corpus byte error rate is 0.14% under --full and 0.07% under --minimal, and the README attributes most of what remains to the highlighting rules rather than the matching itself.
OmniDiff runtime over 2,302 code fixtures (author-measured, 2026-10-31)
Median (p50): 4.2 msMedian (p50)4.2 msp90: 35.1 msp9035.1 msp99: 177 msp99177 msSlowest fixture: 482 msSlowest fixture482 ms
  • p99: goals: p50 within 100ms, p99 within 1s

The non-code story is the differentiator. Pictures are compared pixel by pixel, perceptually, so re-encode noise is not reported as a change, and animations align frame by frame. Fonts are diffed glyph by glyph, archives member by member (nested archives included, Java class files turned into listings), message catalogs message by message, PDFs page by page. Each change is classified on a scale a human reader understands: invisible, imperceptible, artifacts, edited, redrawn, replaced. Non-code accuracy is judged rather than byte-painted: a human names each change's severity and the tool's verdict is compared, and pictures score 69% perfect and 91% near-perfect across 130 judged cases, with the other content types between 82% and 100% (PDFs are 4-for-4, a sample the README itself flags as tiny). The TUI draws real pixels when your terminal speaks the kitty, sixel, or iTerm2 protocol, and falls back to Unicode half blocks everywhere else.

Integration is the second surprise. There is a configuration wizard (omnidiff git configure), a hand-written alternative, and jujutsu support with its own wizard, since jj ignores git's difftool settings entirely (diff-invocation-mode = file-by-file is required, because jj otherwise hands the tool two directory trees). Headless mode prints plain text with 3 lines of context and names the nearest enclosing function, class, or struct for each hunk when that context is not otherwise visible. --mode json emits a schema-described JSON object, which makes the tool usable from scripts and agents that want the diff, not the prose.

OmniDiff under git, jj, and scripts
$ omnidiff git configure

$ omnidiff jj configure

$ git config difftool.omnidiff.cmd 'omnidiff "$LOCAL" "$REMOTE"'

$ GIT_EXTERNAL_DIFF=omnidiff git diff

$ git difftool --tool=omnidiff

$ omnidiff --headless --exit-code before.css after.css

$ omnidiff --mode json before.rs after.rs

Difftastic: the structural incumbent

difftastic (Wilfred/difftastic) is the tool that made structural diff a working category instead of a demo. It parses 30+ languages with tree-sitter and turns AST alignment into a graph problem solved with Dijkstra's algorithm, which is exactly as pleasant as it sounds in practice. The project sits at about 26,100 GitHub stars, has a proper manual, mercurial support, Emacs integrations, and visible ongoing maintenance (0.72.0 is its latest release as I write, cut October 29).

Behavior under imperfect input is conservative by design: on a parse error it falls back to a line-oriented diff with word highlighting, which the README frames as a guarantee that it never claims two syntactically different files are the same. The same choice is why a pure reformat that touches no syntax reads as no change at all, which is the point of the tool. Its known issues are written on its own README rather than hidden: performance and memory use scale poorly on files with many changes, the side-by-side display occasionally confuses, and crashes do get fixed release by release. It does not produce patch files (a declared non-goal) and does not do merges (AST merging is where Mergiraf lives). For reviewing source-only changes where you want the smallest visible unit of change to be a syntax token rather than a line, difftastic remains the tool to beat on maturity and reach.

delta: the pager that stays in its lane

delta (dandavison/delta) never claimed to be semantic. It takes the diff git already produced and makes it readable: all of bat's syntax themes, side-by-side view, line numbers, n/N to jump between hunks, word-level highlighting via a Levenshtein edit inference, blame and grep integration, and support for the OSC-1717 diff metadata spec that lets TUI tools like lazygit render diffs through delta's styling. It is at about 32,600 stars and fresh from a 0.20.1 release.

The reason delta coexists with everything above: it is presentation only. It does not change which hunks exist, it changes how they read. That sounds dismissible until you apply it to a 2,000-line infrastructure refactor, at which point the difference between finishing the diff and skimming it is the whole product. It is also the cheapest install in this post: a pager binary plus your gitconfig, no retraining. If you have not read it, the one-year accounting of what stuck in my dotfiles includes delta and why.

Side by side

One column per tool, one row per question a reviewer actually asks:

Dimension

OmniDiff

difftastic

delta

Job

Read any change, including non-code formats

Read code changes by syntax

Read any line diff comfortably

Model

tree-sitter structural diff (25 languages) plus format-specific binary diffs

tree-sitter AST alignment (graph search)

Styles the same line diff, adds word-level inference

Non-text files

Pictures, archives, fonts, cursors, catalogs, PDFs

Detects binary files and reports their sizes (since 0.65); no content diff

None

Git connection

difftool, GIT_EXTERNAL_DIFF, jujutsu (wizard)

Manual git external diff setup

core.pager, interactive.diffFilter

For scripts

--headless text, --mode json (schema published)

No patch output by design; --check-only --exit-code tests same-AST for tools

Pager only

License

AGPLv3, commercial option

MIT

MIT

State (early Nov 2026)

v0.3.0, about 830 stars

0.72.0, about 26,100 stars

0.20.1, about 32,600 stars

The edges: diffsitter, hunk, and Mergiraf

Three more names belong here without a full head-to-head. diffsitter (afnanenayet) is another tree-sitter AST differ, earlier to the idea in some respects, smaller in community, with documented git and difftool config. hunk (modem-dev/hunk, MIT, about 9,700 stars, v0.24.1, backed by Modem) is a fourth answer to the reading question: a review-first terminal viewer rather than a pager or a structural differ. hunk diff opens the working tree, untracked files included, as a multi-file review stream with sidebar navigation, split and unified layouts, and a watch mode that reloads as files change. hunk show and hunk log cover commits and history, hunk gh pr 123 reviews a GitHub pull request with no gh CLI installed, and hunk patch - reads a diff straight from stdin. It plugs into the same reading seams as delta (set core.pager to hunk pager, or use it as a difftool), auto-detects jujutsu and Sapling checkouts, and it is line-based: its own comparison table marks structural diffing as a no. The 2026-specific part is the agent angle, inline AI and agent annotations beside the code, driven by a review skill your agent runs against the live session. Mergiraf (mergiraf.org, hosted on Codeberg, currently 0.20.0) works the other half of the problem: it is a git merge driver that resolves conflicts on the syntax tree while you rebase, instead of dumping markers on you, and it also integrates with jj.

That pairing closes the loop worth noticing: reading changes structurally and writing merges structurally are two products of the same idea. Difftastic and OmniDiff make review cheaper. Mergiraf makes history rewriting cheaper. It belongs in its own post, and it is easy to imagine it earning one here.

Which one when

  • Almost everyone, first step: stock git diff plus delta. Zero behavior change to your pipeline, one line of config, immediate readability gain on every diff you already read.
  • Code review where the smallest token matters: difftastic. MIT, long-maintained, honest docs. Watch memory on very large, heavily changed files, and expect no patch output.
  • Commits with non-text files, or pipelines that want structured diffs: OmniDiff. Only if AGPL is acceptable to you, and ideally after a week against your own repos rather than the author's corpus, because the accuracy targets are stated, published, and not yet met.
  • Sprawling multi-file reviews, or agent changes to keep an eye on: hunk, via hunk diff. Only if you regularly review sprawling multi-file changes; if you do not, skip it, because delta already covers the quick look.
  • Merge pain rather than review pain: Mergiraf, as a merge driver, not a display tool.
  • CI and anything that applies patches: git itself. These tools read diffs; they do not write them.

The honest limits

  • This is a documentation-based comparison, not a lab. I went through READMEs, manuals, and release notes for all five projects. I did not run OmniDiff's benchmark suite, and none of the speed or robustness figures here are my own measurements.
  • All OmniDiff numbers are author-measured, over the project's published corpus and hardware (dates in the README, most recent run October 31, 2026). They are unusually well-documented, but they are one person's numbers until someone else reproduces them. The project also discloses that development uses substantial AI assistance (currently Claude Code) and is not accepting contributions at this time, so there is no second pair of hands behind these figures yet.
  • The snapshot is early November 2026. Versions and star counts move, and OmniDiff moved fast in the last six weeks (v0.1.0 through v0.3.0 changed accuracy and speed measurably). Re-verify before you pin anything.
  • The accuracy story is the one to watch. If pixel-accurate semantics decide your adoption, read the project's own accuracy section rather than my summary; the gap it describes is real and tracked.
Verified
  • OmniDiff0.3.0 (release 2026-11-01)
  • difftastic0.72.0 (release 2026-10-29)
  • delta0.20.1 (release 2026-10-04)
  • hunk0.24.1 (release 2026-10-25)
  • Mergiraf0.20.0 (Codeberg)

FAQ

Is OmniDiff production ready?

Its own release notes say the interactive TUI and batch mode are ready for daily use as a git difftool, and the published robustness numbers (99.95% of code pairs completing) support that. It is also at v0.3.0 with a small community, so I would treat it as a daily-driver candidate for reading diffs, with stock git diff kept for anything that touches automation.

What does OmniDiff do that difftastic does not?

Two things. Non-text content: pictures, fonts, archives, cursors, PDFs, and message catalogs get a real per-item diff where difftastic has no story outside plain text. And packaging around the diff: a full-screen TUI, hunk context by enclosing function, and JSON output aimed at scripts and agents. Structural source code diffing itself, difftastic does with more history behind it.

Do any of these replace git diff?

No. Every tool here plugs into git's existing seams (pager, difftool, external diff). None produce patch files, and OmniDiff deliberately exits 0 even when files differ unless you pass --exit-code. That default mirrors git diff, which also exits 0 on a difference; --exit-code adds diff(1)'s convention of exiting 1 when files differ, and it is opt-in precisely because OmniDiff's usual non-interactive callers are version control systems that treat any non-zero exit as "the tool failed". One wrinkle: the 7-argument GITEXTERNALDIFF form stays at 0 even with --exit-code, since git treats a non-zero exit there as fatal. Your apply, am, and CI paths stay stock.

Is the accuracy shortfall a real problem for me?

Probably less than the headline suggests. The 60-70% figure counts whole test cases against hand-painted ground truth: 60.0% with zero mismatched bytes under --full and 69.6% under --minimal, rising to 87.5% and 91.5% once a 1% mismatch budget is allowed. The residual byte error over the full corpus is 0.14% under --full and 0.07% under --minimal. The README names the remaining gap: the highlighting rules, not the node matching, own most of it, and the --minimal preset sits closest to how a human paints. It is a target in progress, not a hidden flaw.

Why is OmniDiff AGPL when the others are MIT?

The author's choice, visible in the repo with a separate LICENSE-COMMERCIAL and a subscription path for organizations that cannot adopt AGPL internally without it. It is the single most practical filter in this comparison: put that file in front of whoever owns compliance at your job before running benchmarks.

Further reading

  • OmniDiff: https://github.com/ivankovic/omnidiff
  • OmniDiff showcase in a browser: https://ivankovic.github.io/omnidiff/showcase/
  • difftastic manual: https://difftastic.wilfred.me.uk/
  • difftastic git integration: https://difftastic.wilfred.me.uk/git.html
  • delta: https://github.com/dandavison/delta
  • hunk: https://github.com/modem-dev/hunk
  • Mergiraf: https://mergiraf.org/
  • Our modern Unix replacements, one year later (delta verdict): https://systhoughts.com/posts/modern-unix-replacements-one-year-later

Which of these is in your difftool slot, and has anything in your repos actually gotten easier to read because of it? Drop it in the comments.

Until next time, keep your systems thoughtful.

No comments yet