Skip to content

Git WhyFinds the history that explains the code.

`git blame` tells you who changed it. `git why` finds the commit, the author's real words, and the diff that explain why.

Git Why

See it run

git why "why did making lots of schemas suddenly get slow and memory-hungry"

A real recorded session. Timings are actual latency.

No identifier to grep for, no file to scope to — the question shares almost no vocabulary with the commit that answers it. That mismatch is the whole reason this exists.

git why "TLS backend abstraction and vtls layer" --owners -n 20

A real recorded session. Timings are actual latency.

git blame credits whoever last touched a line; git shortlog credits churn. This weights commits by relevance instead.

An agent using it

An agent asked why schema creation got slow

A real recorded session. Timings are actual latency.

The agent was given a neutral list of what exists — git log, git show, git blame, grep, rg, git why — and no instruction about which to use. Network tools were shadowed, so the GitHub API was not an escape hatch.

It chose history search on its own, found the commit, verified it, and reported the measured numbers including the one axis that regressed.

Two earlier takes of this same recording are worth knowing about. In the first, gh was on PATH and the agent answered from the GitHub API without touching the repository at all. In the second the prompt told it which tool to use for what, which proves nothing: of course it complies. Only the third — neutral list, no network — actually tests whether a model reaches for history unaided.

Honest numbers

On 174 questions derived from six real repositories, each verified unanswerable by keyword search before entering the set:

strategyHit@5MRR
git why0.2870.203
zg0.0400.026
git log --grep0.0110.003
git log -S0.0000.000

18x the best Git-native strategy — and wrong roughly seven times in ten. Both halves are true and both are on the benchmarks page.

When you can name the symbol, git log -S beats this 0.950 to 0.350. The shipped agent skill says so, because a tool that oversells itself makes an agent worse at its job.

Why a semantic index, not a grep

The query below shares no vocabulary with the commit it finds. That is the actual point of a semantic index: it carries the meaning of the change, not just its words. Output is real, from mise run demo, which rebuilds bench/fixtures/demo/build.mjs and runs these queries against it.

text
$ git why "that bizarre bug where reconnecting subscribed twice"

1. 7deab42  Stop duplicate subscriptions after reconnect
   2025-11-20 · Maya Chen

   Reconnecting re-ran the subscribe handler without clearing the previous
   registration, so every reconnect doubled the delivered events.

   src/net/socket.ts
   -export function connect(url) { return new Socket(url); }
   +export function connect(url) {
   +  const s = new Socket(url);
   +  s.on('reconnect', () => resubscribeOnce(s));
   +  return s;
   +}
text
$ git why "why do we keep the session when the refresh token is empty?"

1. f17db20  Fix infinite token-refresh loop
   2025-11-03 · Maya Chen

   Provider X can return an empty refresh token while the current access
   token remains valid. Retrying here puts clients into an infinite loop.

   src/auth/refresh.ts
    export function refresh(session, refreshToken) {
   -  if (!refreshToken) throw new InvalidTokenError();
   +  if (!refreshToken) return session;
      return exchange(refreshToken);
    }

Install

sh
curl -fsSL https://alliecatowo.github.io/git-why/install.sh | sh
sh
npm install -g @alliecatowo/git-why

The package installs a git-why executable, which Git dispatches as the subcommand git why. See Getting started for the first query and first index.

Measured, not claimed

Every number below is written into this page by bench/report.mjs from raw run data, and CI fails if it drifts. Full methodology, dataset provenance and the negative results are in the benchmark report.

174 recall questions — you remember a problem but cannot name anything in the commit that fixed it — derived mechanically from 6 pinned real repositories (curl, redis, requests, ripgrep, caddy, zod). Every question is verified unanswerable by keyword search before it enters the set: if git log --grep or git log -S finds the answer from the question's own words, the case is discarded.

strategyHit@1Hit@5MRRreturned nothing
git why0.2010.3740.2660
zg (semantic code search)0.0170.0400.0262
git log -G0.0060.0170.01115
git log --grep0.0000.0110.0030
git log --grep --all-match0.0000.0000.000109
git log -S0.0000.0000.00015

10.2x zg and 23x the best Git-native strategy — and the only approach that answers nearly every question rather than returning an empty set.

When you can name the symbol, use pickaxe search instead. On cross-file causal questions, git log -S scores Hit@10 0.950 against git why's 0.350. Semantic search has no advantage over a tool you can hand the exact literal.

That boundary is in the skill shipped with the plugin, because a tool that oversells itself makes an agent worse at its job.

Does it help an agent?

Retrieval quality is not the product. The question is whether an agent answering a real question does it more accurately, or in fewer turns, with the tool than without. Four arms over the same frozen tasks, paired per task, with token counts reconciled against the provider's own accounting database.

modelpaired naccuracy W-Lmedian tool calls saved
gemini-3.1-flash-lite61-22.5
claude-haiku-4-591-11
claude-sonnet-580-01
deepseek-v4-flash80-03.5
gemini-2.5-flash-lite62-11
gemini-3.1-flash-lite72-01
gemini-3.5-flash60-00.5 more

Results are mixed across models. At single-digit paired n per model this is descriptive, not significant, and it is reported that way deliberately — the direction is consistent, the magnitude is not established. Full method and per-arm figures in the benchmark report.

Method, per-arm figures and the registered hypothesis are in the benchmark report.

measurementresult
Index across 6 real repos (56,781 commits)5.51–7.84 KB/record
curl-curl (30,000 commits, 182,772 records)1.37 GiB, 7.84 KB/record
Query on curl-curl (30,000 commits) with git why server on384 ms p50, 491 ms p95
The same query with no daemon851 ms p50, 1371 ms p95
Diff/evidence ingestion, real-repo ablationearns its cost, ΔHit@5 +0.375

It is also wrong most of the time. Hit@5 of 0.374 means the right commit is outside the top five on 62.6% of these questions. It beats every alternative on them and still fails on most. Treat a result as a lead to verify with git show, never as established fact.

When to use ordinary Git instead

Git Why is ranked retrieval over a semantic index. That's the wrong tool for some jobs, and Git already has the right one:

  • A known exact stringgit log -S / git log -G are exhaustive; a ranked keyword search is not.
  • An exhaustive searchripgrep over a checkout, or git grep.
  • Verifying causality — similarity is not a timeline. Confirm ancestry with git merge-base, git log --ancestry-path, git show.

Read the full case in How it works.

Released under the Apache-2.0 License.