git-diff-stat is a Rust CLI for git diff --stat with one main opinion: diff stats
are most useful when they highlight non-test code by default.
- non-test-only stats by default across all supported languages, with
--test,--non-test, and--no-test-filter - untracked files included in default stats
- language filtering with
--lang - test-aware filtering for Rust, Python, and JS/TS families
- single-commit and revision-range support
Plain git diff-stat already reports non-test changes across all supported languages, so you
can see production-code churn without test noise:
git diff-stat
git diff-stat --lastWhen you do want a different slice, switch by language, test scope, or revision range:
git diff-stat --lang py --test
git diff-stat HEAD~1..HEAD --lang tsx --no-test-filterThis repository also ships rust-test-audit, a companion CLI for auditing Rust source trees
and flagging files where inline test code has grown large enough to consider extracting into
separate tests.rs modules.
cargo install --path .This installs both git-diff-stat and rust-test-audit.
Copy the compiled binaries into any directory on your PATH, for example:
cp target/release/git-diff-stat ~/.local/bin/
cp target/release/rust-test-audit ~/.local/bin/Download the archive for your platform from GitHub Releases, extract it, and place the git-diff-stat binary on your PATH.
Tagged releases use the vX.Y.Z format, for example v0.1.0.
Release assets are published per platform, for example:
git-diff-stat-v0.1.0-x86_64-unknown-linux-gnu.tar.gzgit-diff-stat-v0.1.0-x86_64-apple-darwin.tar.gzgit-diff-stat-v0.1.0-aarch64-apple-darwin.tar.gzgit-diff-stat-v0.1.0-x86_64-pc-windows-msvc.zip
This repository includes a helper script for cutting a new version tag:
./scripts/release-version.shBy default it bumps the patch version, requires a clean worktree, runs the same checks as ci.yml, updates Cargo.toml and Cargo.lock, then commits, tags, and pushes to origin.
Examples:
./scripts/release-version.sh
./scripts/release-version.sh minor
./scripts/release-version.sh --dry-runGit automatically treats an executable named git-diff-stat as the git diff-stat subcommand. Once the binary is on your PATH, you can run:
git diff-stat
git diff-stat --commit HEAD
git diff-stat --last
git diff-stat --last --no-test-filter
git diff-stat HEAD~1..HEAD --lang py --no-test-filter
git diff-stat --lang py --test
git diff-stat --lang tsx --test
git diff-stat --testgit diff-stat [<rev> | <rev1> <rev2> | <rev-range>] [--lang rs,py,js,ts,jsx,tsx,cjs,mjs] [--test | --non-test | --no-test-filter]Defaults:
--langdefaults to all supported languages:rs,py,js,ts,jsx,tsx,cjs,mjs- test filtering defaults to
--non-test - output always begins with a header line describing the comparison scope, languages, and test scope
That means plain git diff-stat already reports non-test changes across all currently supported languages.
rust-test-audit [--root <dir>] [--path <dir>]... [--format table|json|markdown]Examples:
rust-test-audit
rust-test-audit --format json
rust-test-audit --root /path/to/repo --path winq-coin/src --format markdownDefaults:
--rootdefaults to the current directory--pathdefaults to the current directory
The audit skips tests.rs files and Rust files under tests/, then reports files whose inline
test regions cross configurable density thresholds.
git diff-statgit diff-stat --commit <commit>git diff-stat --lastgit diff-stat <commit>git diff-stat <a> <b>git diff-stat <a>..<b>git diff-stat <a>...<b>
<commit> by itself is treated as <commit> HEAD, so it reports the diff from that commit to HEAD.
--langcurrently uses file extensions.--testand--non-testtreat Rust files undertests/and Rust files imported by#[cfg(test)]module declarations as whole-file test code. Other Rust files still use code-region splitting for#[cfg(test)]modules and test-annotated functions such as#[test]and#[tokio::test].--testand--non-testtreat Python files undertests/,test_*.py,*_test.py, andconftest.pyas whole-file test code. Other Python files split test regions usingdef test_*andclass Test*.--testand--non-testtreat JS/TS family files under__tests__/,e2e/,cypress/, andplaywright/, plus files matching*.test.*,*.spec.*, and*.cy.*, as whole-file test code.--no-test-filterdisables Rust and Python region splitting and reports full-file stats for the selected languages.--langdefaults to all supported languages, so use--lang rs,--lang py, or--lang tsxwhen you want a narrower language set.--lastis sugar for the patch introduced byHEAD, equivalent toHEAD^!.- rendered output starts with an English description line such as
Non-test code stats for rs,py,js,ts,jsx,tsx,cjs,mjs files in the working tree:. - Output is intentionally close to
git diff --stat, but not byte-for-byte identical.