git-fame
v0.4.0
Published
Fast, accurate git contribution stats — lines, commits, files per author.
Maintainers
Readme
git-fame
Fast, accurate git contribution stats — lines, commits, files per author.
Inspired by git-fame (Python), rewritten in TypeScript. 47x faster on real-world repos.
Quick start
npx git-fame .
npx git-fame /path/to/repo
npx git-fame --format json .
npx git-fame --bytype .
npx git-fame --recursive --summary ~/work
npx git-fame -o report.json .Installation
npm install -g git-fame # global CLI
npm install git-fame # library dependencyFeatures
- Two metrics: lines alive in HEAD (blame) + lines added/deleted (log)
- Smart defaults: excludes generated files, ignores whitespace, follows renames
- Fast: parallel blame workers, ~11s on 2800-file repo (Python git-fame: ~530s)
- Breakdown:
--bytypegroups by file extension,--bydir 1by directory - Caching: results cached by commit SHA, instant on repeat runs
- Config file:
.gitfamercpins flags per repo - Multi-repo:
--recursivescans all repos in a directory - Output formats: table, JSON, CSV, Markdown
- File output:
--output report.jsonor--output dir/for per-repo files - Summary:
--summaryaggregates stats across repos in recursive mode - Library + CLI: use as
npx git-fameorimport { analyze } from 'git-fame'
CLI
Usage: git-fame [options] [path]
Options:
-v, --version Output the version number
--format <format> Output format: table, json, csv, markdown (default: table)
--sort <column> Sort by: linesAlive, linesAdded, linesDeleted, commits, files
--limit <n> Show only top N authors
--rev <ref> Analyze at a specific commit, tag, or branch
--from <ref> Start of commit range (used with --to)
--to <ref> End of commit range (used with --from)
--since <date> Only count log entries after this date
--until <date> Only count log entries before this date
--include-whitespace Count whitespace-only changes
--include-binary Include binary files
--include-generated Include generated/vendored files
--exclude-minified Exclude minified files
--no-follow-renames Do not follow renames in blame
--no-mailmap Do not apply .mailmap
--include-globs <a,b,c> Only analyze matching files (comma-separated)
--exclude-globs <a,b,c> Exclude matching files (comma-separated)
--concurrency <n> Parallel blame workers (default: auto)
--no-cache Disable result caching
--bytype Group results by file extension
--bydir <depth> Group results by directory at given depth
--per-author Show breakdown per author (with --bytype or --bydir)
--submodules Walk into submodules
--split-submodules Separate reports per submodule
--recursive Analyze all repos in subdirectories
-o, --output <path> Save output to file or directory
-S, --summary Aggregate summary across repos (with --recursive)
-h, --help Display helpExamples
Default output:
$ git-fame .
┌───────┬────────────┬────────────┬──────────────┬─────────┬───────┐
│ author│ linesAlive │ linesAdded │ linesDeleted │ commits │ files │
├───────┼────────────┼────────────┼──────────────┼─────────┼───────┤
│ Alice │ 5200 │ 12000 │ 3000 │ 120 │ 85 │
│ Bob │ 300 │ 800 │ 200 │ 45 │ 30 │
└───────┴────────────┴────────────┴──────────────┴─────────┴───────┘Breakdown by file type:
$ git-fame --bytype .
┌───────┬────────────┬───────┐
│ group │ linesAlive │ files │
├───────┼────────────┼───────┤
│ .ts │ 113918 │ 2562 │
│ .tsx │ 22490 │ 235 │
│ .css │ 348 │ 18 │
└───────┴────────────┴───────┘Filter by file type:
$ git-fame --include-globs '*.ts,*.tsx' .Recursive (multiple repos):
$ git-fame --recursive ~/work --limit 10Save to file (format inferred from extension):
$ git-fame -o report.json .
$ git-fame -o report.csv .
$ git-fame -o report.md .Directory output (one file per repo):
$ git-fame --recursive --format json -o ./reports/ ~/workCross-repo summary:
$ git-fame --recursive --summary ~/work
$ git-fame --recursive --summary --format json -o summary.json ~/workConfig file
Create .gitfamerc in your repo root to pin default flags:
{
"format": "table",
"includeGlobs": ["*.ts", "*.tsx"],
"excludeGlobs": ["*.test.ts"],
"limit": 20,
"sort": "linesAlive"
}CLI flags override config values.
Library API
import { analyze, render } from 'git-fame';
const report = await analyze({ path: '/path/to/repo' });
console.log(render(report, 'table'));import { analyze } from 'git-fame';
const report = await analyze({
path: '.',
include: { generated: false },
includeGlobs: ['*.ts', '*.tsx'],
groupBy: { type: 'extension', depth: 0 },
});
console.log(JSON.stringify(report, null, 2));Multi-repo:
import { analyzeMany } from 'git-fame';
const reports = await analyzeMany({ path: '/workspace', recursive: true });Cross-repo summary:
import { analyzeMany, summarize, render } from 'git-fame';
const reports = await analyzeMany({ path: '/workspace', recursive: true });
const summary = summarize(reports);
console.log(render(summary, 'table'));Performance
Benchmarked on a 2800-file TypeScript repo (Apple Silicon):
| Tool | Time | vs Python | | ----------------- | ------- | -------------- | | Python git-fame | 530s | baseline | | git-fame | 11s | 47x faster | | git-fame (cached) | <0.5s | instant |
How it works
- Discover —
git ls-files, filter binary/generated/minified - Log —
git log --numstatfor additions/deletions per author - Blame — parallel
git blame --porcelain -w -M -Cvia persistent shell workers - Assemble — merge into a typed
Report
Requirements
- Node.js >= 20
- git installed
License
MIT
