TL;DR:
- Difftastic (
dtf) is a structural diff tool that parses source code into syntax trees before diffing, so reformatting and whitespace changes don’t pollute the output - It supports 30+ languages natively and falls back to a line-oriented diff for unsupported file types
- Set it as your
GIT_EXTERNAL_DIFForgit difftoolto get structural diffs inline in your existing workflow — no other setup required
What’s Wrong With Textual Diffs
Standard git diff works on lines. Two lines are different if any character on them differs. This means:
- Reformatting a function to wrap arguments across multiple lines shows up as a massive diff
- Adding a trailing comma in Python, JavaScript, or Rust shows as a changed line even though the code is semantically identical
- Renaming a variable with a search-replace shows every occurrence as independent changes
- Moving a block of code up 20 lines shows as a deletion and a separate addition rather than a move
None of these are wrong — they accurately describe which lines changed. But they describe text changes, not code changes. When you’re reviewing a PR, you usually care about the latter.
Difftastic fixes this by parsing source files into their abstract syntax representation before comparing. Two nodes that are syntactically equivalent are treated as unchanged even if their textual representation differs.
How It Works
Difftastic is written in Rust by Wilfred Hughes. It uses tree-sitter grammars — the same parsing layer used by Neovim’s syntax highlighting and GitHub’s code navigation — to parse source files. The diff algorithm then operates on the resulting tree nodes rather than raw lines.
The output groups syntactic changes and displays them side-by-side with line numbers, similar to a split-diff view. Changed nodes are highlighted; unchanged nodes are greyed out. The format is designed to be read in a terminal and works with standard pager tools.
For files in unsupported languages, difftastic falls back to a textual diff with improved alignment (it uses a different LCS algorithm than standard diff that produces more human-readable alignment in practice).
Installation
# macOS
brew install difftastic
# Arch Linux
pacman -S difftastic
# Cargo (any platform)
cargo install difftastic
# Prebuilt binaries available on the GitHub releases page
Verify:
difft --version
Integrating with Git
As a one-off for a specific diff:
GIT_EXTERNAL_DIFF=difft git diff HEAD~1
GIT_EXTERNAL_DIFF=difft git show <commit>
GIT_EXTERNAL_DIFF=difft git log -p --follow src/main.rs
As a permanent alias in your shell:
alias gd='GIT_EXTERNAL_DIFF=difft git diff'
alias gs='GIT_EXTERNAL_DIFF=difft git show'
As a git difftool (invocable on demand):
git config --global diff.tool difftastic
git config --global difftool.difftastic.cmd 'difft "$LOCAL" "$REMOTE"'
git config --global difftool.prompt false
# Use with: git difftool HEAD~1
As a global default (all git diffs use difftastic):
git config --global diff.external difft
The global default replaces git diff output site-wide, including in git log -p. Some people prefer the alias or difftool approach to keep standard text diffs available.
Practical Examples
Whitespace and formatting change:
A commit that runs gofmt on a Go file would show dozens of changed lines in a standard diff. Difftastic shows zero changes if the code is semantically identical after formatting.
Argument reordering:
# Before
result = process(data, config, verbose=True)
# After
result = process(config, data, verbose=True)
Standard diff: two changed lines. Difftastic: highlights the swapped arguments specifically.
Import block reorganisation:
Sorting or grouping imports is a common refactoring that produces noisy standard diffs. Difftastic identifies which imports were added, removed, or moved rather than showing each line independently.
Language Support
Difftastic supports 30+ languages including Python, JavaScript, TypeScript, Rust, Go, C, C++, Java, Kotlin, Ruby, Haskell, Clojure, JSON, YAML, TOML, HTML, CSS, and several others. The full list is in the project README.
For JSON and YAML specifically, the structural diff is particularly useful — it catches key additions, removals, and value changes without noise from whitespace normalisation.
For Markdown, difftastic applies text-based diffing (prose isn’t a syntax tree in a meaningful sense), but with improved alignment.
Performance
Difftastic is fast for most files. It’s written in Rust and the tree-sitter parsing is efficient. For very large files (thousands of lines), the diff algorithm can be slower than standard git diff because tree comparison is more computationally expensive than line comparison. There’s a --byte-limit flag to fall back to line-based diffing for files over a size threshold.
In practice, this isn’t a noticeable issue for code review on typical application files. It can matter if you’re diffing generated files or minified assets — though those usually shouldn’t be in version control anyway.
When to Use It
Difftastic is most valuable during code review and before writing commit messages — the two moments when you want to understand what actually changed rather than what lines moved.
It’s less useful as a default for quick sanity checks (git diff to confirm staged changes before committing) because the side-by-side output takes more screen space than a standard unified diff and the structural comparison occasionally reorganises context in surprising ways for very small changes.
The practical setup most developers end up with: a gd alias that uses difftastic for review-style inspection, and standard git diff still available for quick checks.
Relation to Delta
Delta (covered separately) enhances textual git diffs with syntax highlighting, side-by-side view, and improved formatting. It operates on the same line-oriented diff output as standard git diff.
Difftastic and Delta solve different problems: Delta makes textual diffs prettier; difftastic makes diffs semantically accurate. They’re not mutually exclusive — some developers use difftastic for PR review and delta for quick terminal diffs — but you’d typically pick one as your primary git diff enhancement.
If formatting noise in diffs is your main frustration, difftastic addresses it directly. If you want richer display of the same textual diff, Delta is the better fit.