Metrics reference
Unless stated otherwise a metric is computed over the commits that survive the filters (--since, --until, globs, --max-files), for files that still exist at HEAD. Pure renames (0 lines added and deleted) are used to follow identity but never count as revisions.
Revisions and churn
- Revisions: number of commits that touched a file.
- Added / deleted: summed numstat lines. Binary files count as 0.
- Churn by period: commits, distinct authors, distinct files and lines per day, week, month or year, using the author's local date.
- Caveat: a refactor that reindents a file inflates lines but counts as one revision. Revisions are the more robust signal and are what hotspots use.
Complexity
- LOC: non-blank lines that are not comment-only. Comment prefixes are chosen by extension (
#,///* * */,--). - Indentation complexity (Tornhill style): every code line contributes its logical indentation depth; the file's value is the sum. Depth is leading whitespace divided by the file's detected indent unit (most common positive step between consecutive indent widths, default 4; a tab counts as 4 columns). Mean and max are also computed.
- Cyclomatic complexity (Python only): per function
1 + decision points(if,for,while,except, conditional expression,matchcase, each boolean operator beyond the first operand, each comprehensionforandif). The file value is the sum over all functions plus decisions at module level. Nested functions count separately. Files with syntax errors have no value. - Caveat: indentation grows with LOC, so big files score high by construction. That is intended (big and tangled is what you want to see) but it means two files are only comparable within one language.
Hotspot score
score = 100 * (revisions / max revisions) * (complexity / max complexity) over the analysed files. It is relative to the repository, so use it for ranking, not as a threshold. fixes counts revisions whose message is classified as a fix.
Trend
Up to N commits that touched the file are sampled evenly; each blob is read with git cat-file using the file's name at that commit (so renames are followed) and re-measured.
Temporal coupling
For every commit, each pair of files changed together gets one shared revision. For files A and B:
- support (
shared): commits touching both. - degree:
shared / ((revs_A + revs_B) / 2)as a percentage. - confidence A to B:
shared / revs_A; "when A changes, B changed too in this share of cases". B to A is the reverse. - module: the first
--module-depthdirectories of the path. A pair is cross-module when the modules differ; the module matrix sums shared revisions per module pair. - Caveats: bulk commits are skipped by
--max-filesbecause they couple everything to everything. Tests coupled to their code are expected, not a smell. Pairs below--min-sharedare dropped as noise.
Knowledge
- Ownership of a file by an author is lines added by them across the window (default) or surviving lines per
git blame -w(--blame). - Main developer: largest share; ties break alphabetically.
- Knowledge loss: files where authors listed in
--departedhold more than 50% combined. - Bus factor of a directory: each file carries one unit of knowledge split by ownership share; authors are taken in descending order of total knowledge until they hold more than 50% of the directory's units. The count is the bus factor. Directories are reported down to
--depth, and the root is.. - Caveats: lines added reward verbosity; the first import commit is ignored when it is a bulk commit, which can hide the real original author; authors who are active today are not distinguished from those who left unless you say so.
Team metrics
- Heatmap: commit count by weekday (Monday first) and hour in the author's own timezone.
- Code age when modified: for each change to a file, days since the file's first appearance anywhere in the history (not only the window). Median and 90th percentile are reported. It is a proxy for how old the code is when someone has to touch it, not true lead time.
- First-time contributors: authors whose first commit in the full history falls inside the window.
- Commit size: lines added plus deleted per commit, in buckets 1-10, 11-50, 51-200, 201-500, over 500, with median and p90. A proxy for pull-request size.
- Fix ratio: share of commits whose subject matches a conventional
fix:/fix(scope):/hotfix:prefix or contains fix, fixes, fixed, bug, bugfix, hotfix, crash, regression or repair as a whole word. "prefix" does not match "fix". Messages in other languages are not recognised.