difftastic (difft): Structural, Syntax-Aware Diffs
difftastic (invoked as difft) compares files by their syntax tree rather than line by line, so changes that only reformat code are shown as unchanged.
difftastic understands the grammar of many languages. It is excellent for review because it hides noise, but its output is not a unified patch, so do not feed it to patch.
What it does
difft parses both files, diffs the resulting syntax trees, and prints a structural, side-by-side comparison. Because it works on structure, whitespace-only and pure-reformatting changes register as no change. Its exit code reflects whether it found differences.
Common usage
difft old.rs new.rs
# use as Git's external diff tool
GIT_EXTERNAL_DIFF=difft git diff
# configure permanently
git config --global diff.external difftOptions
| Flag / usage | What it does |
|---|---|
| --display <mode> | side-by-side, side-by-side-show-both, or inline |
| --color <when> | always, auto, or never |
| --language <name> | Force a language when detection is wrong |
| GIT_EXTERNAL_DIFF=difft | Use difft as Git's diff engine for one command |
| diff.external=difft | Configure difft as the permanent external diff |
In CI
difft is a review aid, not a patch producer: its output cannot be applied with patch or git apply. For a readable log of what changed, run difft --color always old new. Keep any staleness gate on plain diff or git diff, because difft may report "no changes" for a reformat that a byte-level gate still wants to catch.
Common errors in CI
"difft: command not found" means difftastic is not installed (the binary is difft, the package is difftastic). If Git shows nothing under GIT_EXTERNAL_DIFF=difft, the file type is binary or unsupported and difft falls back. Piping difft output into patch fails with "malformed patch" because it is not a unified diff.