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.

Screenshot of difftastic

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.difftastic

Usage

# Diff two files directly
dtl old.rs new.rs

# Use as a drop-in for diff
dtl file1.py file2.py

Git 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 = difft

Why 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.