# Git history & co-changes

Hotspots, ownership, bus factor, and co-change pairs, the signals repowise mines from your last 5,000 commits that no AST analysis can produce.

Static analysis tells you what the code *is*. Git history tells you
how it *behaves over time*. Repowise mines your last 5,000 commits by default
(configurable up to 10,000 with `--commit-limit`) for behavioural
signals static tools can't produce. Merge commits are tracked as their
own count beside the total, not folded into it, so "how often
does this file change" isn't inflated by a merge that just replays other
people's commits. History follows renames, so a file's age and hotspot
standing survive a move or a rename.

## Hotspots

A hotspot is a file whose recency-weighted churn (180-day half-life)
sits in the top quartile of the repository and that clears two activity
floors: at least 3 commits in the last 90 days, plus either 8 or more
commits or a decayed churn score of at least 0.5. Complexity is not part
of the flag; the churn x complexity chart and the health score add it.
Hotspots get flagged in the dashboard, in `CLAUDE.md`, and surfaced by
[`get_risk`](https://docs.repowise.dev/mcp/get-risk) before your agent touches them.
Non-code files (docs, config, workflows, data) carry commit history like
anything else, but stay out of the hotspot and churn-percentile
population: a churned README should not compete with a churned module
for the same ranking.

## Ownership

`git blame` aggregated into ownership percentages per engineer per
file. Surfaces:

- **Primary owner**: who has historically touched this file most.
- **Recent owner**: the active maintainer (in case it's different).
- **Contributor count**: how many engineers have touched it.

Identity is canonicalized before any of this is counted: GitHub's
per-commit `noreply` addresses for one login are folded onto a single
key, and a few narrower, guarded edges (a distinctive login bridging to
a real email, a shared machine-local host label) merge further. Bots are
detected and excluded from people counts. Two contributors are never
merged just because they share a display name; every merge beyond an
exact email match is guarded and reversible.

## Bus factor

For each file: how many people could leave the team before nobody
owns it? `bus_factor: 1` means a single person owns >80% of the
history. Surfaced as a knowledge-risk warning in the ownership view
and in `CLAUDE.md`.

## Co-change pairs

Files that change together in the same commit **without an import
link** between them. This is hidden coupling, the kind AST analysis
cannot detect. Often the most expensive coupling because no static
tool will warn you about it.

[`get_context`](https://docs.repowise.dev/mcp/get-context) surfaces co-change partners
alongside direct dependencies; [`get_risk`](https://docs.repowise.dev/mcp/get-risk) flags
co-change warnings on PR blast-radius analysis when a changed file's
historical partner is missing from the change set.

## Contributor profiles and reviewer suggestions

Every author with commits gets a profile: modules they own, top files,
co-authors, a commit-category mix (feat / fix / refactor / docs / test
/ chore / perf), silo modules they're solely on, and bus-factor risk
files. Paste a PR's file list into Blast Radius and repowise ranks
likely reviewers by direct authorship, co-change partnership, and
recency.

## Significant commits

The last 10 *meaningful* commit messages per file (filtered: no
merges, no dependency bumps, no lint runs) are passed to the LLM
during wiki generation. The model uses them to explain *why* the file
is shaped the way it is, not just what it does.

## Trend signals

Computed from the rolling commit-rate ratio:

- **Churn trend**: `increasing` / `decreasing` / `stable` based on
  the 30-day vs 60-day rate (cutoffs at 1.5× and 0.5×).
- **Change pattern**: `feature-active`, `fix-heavy`,
  `primarily refactored`, `dependency-churn`, or `mixed-activity`,
  derived from commit message classification.
- **Change magnitude**: lines added, lines deleted, average commit
  size in the last 90 days.

## See it on a file

From the CLI, pull a file's hotspot bit, ownership, and co-change partners
with `--include ownership`:

```bash
repowise context src/auth.py --include ownership
```

From an agent, the same block plus [`get_risk`](https://docs.repowise.dev/mcp/get-risk) for
churn, bus factor, and co-change warnings:

```python
get_context(targets=["src/auth.py"], include=["ownership"])
get_risk(targets=["src/auth.py"])
```

## Workspace mode

In a workspace, all of the above is computed per repo *and* across
repos. Cross-repo co-changes (files in different repos that move
together) are first-class signals and surface in
[`get_context`](https://docs.repowise.dev/mcp/get-context) responses.

> **Note**
>
> **Why a 5,000-commit default?** Going higher gives diminishing
> returns and slower indexing. Tune with `--commit-limit` on `init`
> (cap is 10,000). History windows (90-day churn, prior defects, decay,
> blame age) are measured from the indexed commit's date by default, so
> re-indexing an unchanged tree on a later day gives the same scores; set
> `REPOWISE_GIT_WINDOW_ANCHOR=now` to measure from wall-clock time instead.
