difftastic
A structural diff tool that understands syntax — diffs code by its AST, not by lines, so renames and reformats don't produce noisy output.
difftastic (dtl) is a diff tool that compares files based on their syntax
tree rather than their raw lines of text. Where a traditional diff sees any
change in a line as noteworthy, difftastic understands the structure of the code
and only highlights changes that are semantically meaningful — ignoring pure
reformatting, whitespace shifts, or moved brackets entirely.
It supports over 30 programming languages via Tree-sitter parsers, and falls back gracefully to a line-oriented diff for unsupported file types.
Features
- Syntax-aware diffing — uses Tree-sitter to parse files into ASTs and diffs the trees, not the text
- Ignores formatting noise — moving a block of code, rewrapping a long line, or adjusting indentation produces no diff output if the semantics are unchanged
- Side-by-side display — shows old and new versions in two aligned columns,
similar to
delta --side-by-side - 30+ language support — Rust, Python, JavaScript, TypeScript, Go, C, C++, Ruby, JSON, HTML, CSS, and many more
- Plain-text fallback — files in unsupported languages still get a readable line-based diff
- Git integration — drops in as a git diff driver with two lines of config
Installation
cargo install difftastic
Or via your system package manager:
# macOS
brew install difftastic
# Arch Linux
pacman -S difftastic
# Debian / Ubuntu
apt install difftastic
# Fedora
dnf install difftastic
# Nix
nix-env -iA nixpkgs.difftasticUsage
# Diff two files directly
dtl old.rs new.rs
# Use as a drop-in for diff
dtl file1.py file2.pyGit Integration
Add difftastic as git's diff tool in ~/.gitconfig:
[diff]
tool = difftastic
[difftool]
prompt = false
[difftool "difftastic"]
cmd = difft "$LOCAL" "$REMOTE"
[alias]
dft = difftool
Then use it with:
git dft
git dft HEAD~1
git log -p --ext-diff # show difftastic diffs inline in git log
You can also set it as the default external diff driver without changing your
diff.tool:
[diff]
external = difftWhy it matters
Traditional diffs are line-oriented. When you move a function, extract a
variable, or run a formatter across a file, the output is a wall of red and
green that obscures the real change. Difftastic cuts through that noise by
understanding that foo( bar ) and foo(bar) are the same expression, and that
a function moved from line 50 to line 120 is a move, not a deletion and an
insertion.
It's particularly transformative during code review — the diff you see maps directly to the intent of the change, not the mechanical diff of the bytes.