Best practices¶
Interpreting the metrics honestly¶
Metrics describe code, not people. Commit counts and line totals measure activity in files, not productivity or value. A contributor who reviews, designs, or debugs appears nowhere in GitIntel's output. Do not use these reports for performance evaluation.
Churn is not quality. A file with high churn may be under active, healthy development. The hotspot score points at files worth a conversation — it does not claim they are defective.
Ownership is historical. It is derived from commit diffs, so it describes who has worked on
a file, not whose code survives in it today. When "who wrote the line that broke" matters, use
git blame.
Aggregate views hide imports. A repository that started with a squashed import commit attributes tens of thousands of lines to whoever performed the import. Check the Most Changed Files table for a single enormous commit before drawing conclusions.
Getting accurate data¶
- Analyze a full clone. Shallow clones (
--depth 1) truncate history and every metric with it. - Know which branch you are on. Analysis follows
HEAD. - Normalize author identities first. GitIntel does not apply
.mailmap. If the same person commits under several names, consolidate their Git configuration going forward; historical entries will still appear separately. - Exclude nothing manually. There is no ignore mechanism, so generated files and lockfiles
will appear. Filter them out downstream with
jq:
gitintel --quiet hotspots . --format json \
| jq '[.hotspots[] | select(.file | test("(lock|\\.min\\.)") | not)]'
Large repositories¶
Runtime scales with the number of commits and the size of each commit's diff, because every commit is diffed against its first parent.
- Expect a repository with tens of thousands of commits to take minutes, not seconds.
- The commit walk happens once per process, so prefer one command per report rather than
running
analyze,ownership, andhotspotsin a tight loop over the same repository. - Redirect JSON to a file once and query it repeatedly instead of re-running GitIntel:
COLUMNS=200 gitintel --quiet analyze . --format json > analysis.json
jq '.summary' analysis.json
jq '.contributors[:5]' analysis.json
- Memory holds the entire commit list with per-file changes. Very large histories therefore use noticeably more RAM; if that becomes a problem, analyze a narrower branch.
Scripting¶
- Put global options first:
gitintel --quiet analyze . --format json. - Set
COLUMNSto a large value so Rich does not wrap long paths. - Treat exit code
1as "GitIntel could not answer" — an invalid repository or an unknown--filepath. See Exit codes and errors. - Do not parse the
tableformat; it is intentionally cosmetic and truncates paths.
Team workflows that work well¶
| Cadence | Command | Purpose |
|---|---|---|
| Per pull request | ownership --file for each changed file |
Reviewer selection |
| Per pull request | hotspots --format markdown |
Flag risky files during review |
| Monthly | analyze --format json, archived |
Trend of activity and contributor spread |
| Before a refactor | hotspots + ownership --file |
Identify conflict-prone files and their owners |
| Onboarding | analyze then ownership |
Orient a new contributor in a day, not a week |
Privacy considerations¶
Reports contain author names, and JSON output for analyze includes contributor names but not
email addresses. Ownership output identifies contributors by name. Treat generated reports the
same way you treat your commit history — if the repository is private, its reports are too.