Git Why について
Git Whyは、開発者やコーディングエージェント向けのローカル優先のGit履歴検索ツールで、意味検索と全文検索を組み合わせます。コミット、作者の実際の記述、関連差分を根拠として返し、独自に説明を生成するものではありません。
主な機能
- 01Git履歴の意味検索と全文検索
- 02コミット、作者の記述、差分の表示
- 03リポジトリ索引の逐次更新
- 04任意で使える常駐索引サービス
- 05MCP対応とエージェントプラグイン
活用シーン
- 01問題は覚えているがコミット用語が不明なときの履歴検索
- 02コード変更に関するコミット根拠の確認
- 03エージェントのワークフローへの履歴検索追加
MCP 対応
`npx -y @alliecatowo/git-why mcp`でMCPサーバーを起動し、MCPクライアントにGit履歴検索を提供できます。エージェントプラグインにもサーバーが含まれています。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
2掲載時のツール一覧 · 2 週間前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| cwd | string | いいえ | リポジトリのディレクトリ。デフォルトはサーバープロセスのディレクトリです。 |
| mode | enum | いいえ | hybrid | text | semantic |
| sort | enum | いいえ | relevance | oldest | newest |
| limit | number | いいえ | |
| query | string | はい | 自然な言葉で表現した質問です。「なぜ諦める前に 2 回再試行するのか」「webhook が重複配信されたあのバグは何だったのか」など。ファイルではなく症状や判断を説明してください。ファイルの検索には `git log -- <path>` があり、こちらのほうが優れています。 |
| groups | array | いいえ | コミット単位の RRF で統合する追加クエリグループです。 |
| owners | boolean | いいえ | この領域を確立した人物も返します。現存する行数(git blame)やコミット数(git shortlog)ではなく、コミットの関連度順に並べます。「誰がこれを作ったか」「誰にレビューを依頼すべきか」「誰が詳しいか」といった質問に使用してください。 |
| temporal | object | いいえ | 省略可能な時間検索条件です。省略した場合、CLI がクエリを分解します。 |
| temporal.type | enum | いいえ | first | last | removed | changed_when | before | after | between | around | timeline |
| temporal.anchor | string | いいえ | |
| temporal.anchorEnd | string | いいえ |
詳細
Git Why
git blame は誰がコードを変更したかを教えてくれます。git why は、その変更に至る経緯を見つけます。
Git の履歴を対象に、ローカル優先でセマンティック検索と全文検索を行います。実際のコミット、作者本人の言葉、関連する差分を返します。証拠を取得するものであり、独自の説明を生成するものではありません。
bench/fixtures/demo/build.mjs から小さなフィクスチャリポジトリを再構築し、2 つのクエリを実行する mise run demo の実際の出力です。ここにあるものはすべて実際の出力で、手書きではありません。コマンドを 1 つ実行するだけで再現できます。
curl、zod、redis などの実際のリポジトリに対する出力や、これが適切なツールではない事例については、docs/examples.md または記録済みのターミナルセッションをご覧ください。
$ 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;
+}
$ 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);
}
インストール
npm からインストールします(Node >= 22.12)。
npm install -g @alliecatowo/git-why
または Homebrew を使用します(macOS と Linux 対応。node もインストールされます)。
brew install alliecatowo/tap/git-why
またはソースからビルドします。
git clone https://github.com/alliecatowo/git-why.git
cd git-why
npm ci
npm run build
npm install -g .
パッケージをインストールすると git-why 実行ファイルが追加され、Git はこれをサブコマンド git why として実行します。エイリアスの設定は不要です。固定バージョン、GitHub リリースの tarball、ソースからのビルド、アンインストールなど、その他のインストール方法はdocs/install.mdをご覧ください。
初回実行
cd your-repo
git why "why do we retry twice before giving up"
最初のクエリでは小さな埋め込みモデル(約 32 MB、チェックサム検証済み)をダウンロードし(~/.cache/git-why/models にキャッシュされます)、リポジトリの履歴を .git/why/ にインデックス化します。それ以降のクエリでは差分のみが処理されます。プロキシ経由またはオフラインで利用する場合は、docs/operations.mdの HTTPS_PROXY、GIT_WHY_MODEL_BASE_URL(ミラー)、GIT_WHY_OFFLINE をご覧ください。git why status でインデックスが最新かどうかを確認できます。
エージェントで使う
plugins/ には 2 つのプラグインが用意されています。
| plugin | 提供内容 |
|---|---|
git-why | MCP サーバー、ルーティングスキル、インデックス管理スキル。 |
git-why-full | 同じ内容に加えて、現在のコードを検索するための zg と、複数回の検索が必要な質問に対応する履歴探索エージェント。 |
OpenCode ユーザー向けには opencode/ も用意されています。MCP 登録を含む opencode.json と、AGENTS.md のフラグメントが含まれています。
このスキルが実際に教えるのは、履歴を使うべきでない場面です。シンボル名が分かる場合は git log -S を使うようエージェントに伝えています。このケースでは、このツールの性能が実測で劣るためです(Hit@10 は 0.350 に対して 0.950)。また、コードの現在の状態を調べる場合は、履歴ではなくコード検索を使うよう伝えています。自分のツールが常に最適だと主張するスキルは、エージェントの仕事の質を下げます。
その他の MCP クライアントでも、サーバーを直接実行できます(npx -y @alliecatowo/git-why mcp。インストール済みの場合は git why mcp)。MCP registry では io.github.alliecatowo/git-why として登録されています。
docs/plugin.mdをご覧ください。
高速化する(任意)
git why server on
インデックス、埋め込みモデル、系譜テーブルをクエリ間で開いたままにします。30,000 コミットの curl では、クエリあたり 569 ms から 286 ms に短縮されます。起動していれば、検索時に自動で利用されます。
検索の失敗原因になることはありません。デーモンが起動していない場合、接続できない場合、またはインデックスが移動した場合でも、クエリは直接実行されます。--daemon=direct はデーモンを使用せず、--daemon=server はデーモンの起動を必須とします。詳しくはdocs/daemon.mdをご覧ください。
理由
git log --grep で一致するのは、すでに知っている単語だけです。コードが変更された理由は通常コミットメッセージに書かれていますが、その正確な表現を覚えていることはほとんどありません。数か月後に覚えているのは、自分の言葉で表した 問題 です。
上の最初の例をもう一度見てください。検索語は「再接続でサブスクライブが二重になる」ですが、コミットのタイトルは「再接続後の重複サブスクリプションを停止する」です。語彙はほとんど共通していません。これは Git Why が見せ場を作っているからではありません。これこそが、セマンティックインデックスの本質です。変更の単語だけでなく、その意味も保持し、正確な用語を知っている 場合 に備えて通常のキーワードインデックスも併用します。
Git Why が取得するのは、過去の証拠、つまりコミット、作者が実際に書いた言葉、関連する差分です。過去のコミットメッセージは作者による主張であり、意図を誤りなく記録したものではありません。また、理由がコミットに記録されていない場合もあります。Git Why がそうした理由を捏造することはありません。
主張ではなく、実測値
以下の数値はすべて、生の実行データから bench/report.mjs がこのファイルに書き込んだものであり、値に変化があれば CI が失敗します。ここに手入力された数値はありません。詳しい手法、制約、否定的な結果については、docs/report.md をご覧ください。
通常なら使うツールとの比較
174 件の 再現率に関する質問です。修正された問題は覚えているものの、コミット内の名前を特定できない状況を想定しています。6 つの実在するリポジトリ(curl、redis、requests、ripgrep、caddy、zod)を固定し、そこから機械的に導き出しました。各質問は、対象に含める前に キーワード検索では回答できないことを検証しています。git log --grep または git log -S で質問に含まれる言葉から答えが見つかったケースは、対象から除外しています。
| 戦略 | Hit@1 | Hit@5 | MRR | 何も返さなかった数 |
|---|---|---|---|---|
| git why | 0.201 | 0.374 | 0.266 | 0 |
| zg(セマンティックコード検索) | 0.017 | 0.040 | 0.026 | 2 |
| git log -G | 0.006 | 0.017 | 0.011 | 15 |
| git log --grep | 0.000 | 0.011 | 0.003 | 0 |
| git log --grep --all-match | 0.000 | 0.000 | 0.000 | 109 |
| git log -S | 0.000 | 0.000 | 0.000 | 15 |
zg の 10.2 倍、最良の Git 標準戦略の 23 倍です。また、空の結果を返すのではなく、ほぼすべての質問に答える唯一の手法です。
劣る場面
シンボルの名前がわかる場合は、代わりにピックアックス検索を使ってください。複数ファイルにまたがる因果関係の質問では、git log -S の Hit@10 は 0.950 で、git why の 0.350 を上回ります。正確なリテラルを指定できるツールに対して、セマンティック検索に優位性はありません。
この境界を正直に示すことが、適切な位置づけです。提供されているスキルでは、エージェントに次の両方を伝えています。
- 用語を特定できない →
git why - 用語を特定できる →
git log -S - 履歴ではなく現在のコードを調べる →
zg
規模とコスト
エージェントに役立ちますか?
検索品質そのものが目的ではありません。実際の質問に回答するエージェントが、このツールを使うことで、使わない場合より正確に、あるいは少ないターン数で回答できるかが重要です。同じ固定タスクを使った4つの条件をタスクごとにペアにし、トークン数はプロバイダー独自の会計データベースと照合しました。
| モデル | ペア数 | 正解率 W-L | 節約できたツール呼び出しの中央値 |
|---|---|---|---|
| gemini-3.1-flash-lite | 6 | 1-2 | 2.5 |
| claude-haiku-4-5 | 9 | 1-1 | 1 |
| claude-sonnet-5 | 8 | 0-0 | 1 |
| deepseek-v4-flash | 8 | 0-0 | 3.5 |
| gemini-2.5-flash-lite | 6 | 2-1 | 1 |
| gemini-3.1-flash-lite | 7 | 2-0 | 1 |
| gemini-3.5-flash | 6 | 0-0 | 0.5増加 |
モデルによって結果はまちまちです。モデルごとのペア数が1桁台のため、これは記述的な結果であり、統計的に有意なものではありません。そのように意図的に報告しています。方向性には一貫性がありますが、効果の大きさは確定していません。詳しい手法と条件ごとの数値は、ベンチマークレポートをご覧ください。
手法、条件ごとの数値、事前登録した仮説については、docs/report.mdをご覧ください。
| 測定項目 | 結果 |
|---|---|
| 実際の6つのリポジトリにわたるインデックス(56,781コミット) | 5.51–7.84 KB/レコード |
| curl-curl(30,000コミット、182,772レコード) | 1.37 GiB、7.84 KB/レコード |
curl-curl(30,000コミット)でのクエリ git why server on | p50 384 ms、p95 491 ms |
| デーモンなしで同じクエリを実行 | p50 851 ms、p95 1371 ms |
| 差分/エビデンスの取り込み、実際のリポジトリでのアブレーション | コストに見合う、ΔHit@5 +0.375 |
有効だったこと、そうでなかったこと
8つの最適化を実装して測定しました。有効だったのは1つだけです。
有効だったのは、質問とコミット自身のメッセージとの語彙的な重なりを、結果リストより深い候補プール内で再ランキングする方法です。重みは開発用の半分のデータで選び、残りの保留データで一度だけ評価しました。一度も見ていないケースでMRRが26%、Hit@1が44%向上しました。これを採用しました。
効果がなかった7つは、文章向けに調整した埋め込みモデル、疑似関連性フィードバック、文章形式のコミットに対するペナルティ、呼び出し元側でのクエリの言い換え、結果ウィンドウの拡大、構造的な展開、フレーズの融合です。いずれもMRRを改善しませんでした。
差を生んだのは、より良いアイデアではなく、問いの立て方でした。7つの方法はすべて「これでランキングは改善するか」と問いかけていました。有効だった方法は、まず「正しいコミットは実際にどこにあるのか」と問いかけました。その結果、コーパスの4分の1は検索されているものの順位が5位より下であり、これは並べ替えの問題だと分かりました。一方、42%はそもそも検索されておらず、これは並べ替えの問題ではありません。詳しくはdocs/decisions.mdをご覧ください。
残された改善余地は、この42%です。つまり、埋め込み自体の再現率に関する問題です。現在は推測ではなく測定しています。固定プール上で10個のモデルを比較したdocs/embedding.mdをご覧ください。Transformer埋め込みモデルは、採用済みの静的モデルに対してMRRが**jina-v2-smallで+41%、jina-v2-baseで+64%**となる一方、インデックス作成時間はそれぞれ191倍、1287倍かかり、さらにONNXランタイムも必要です。どちらもオプトインで利用できます。デフォルトは高速で依存関係のない状態を維持します。数秒でインストールでき、1分以内にインデックスを作成できるツールが、いつの間にか15時間必要なツールになってしまうべきではないからです。
また、大半の場合は間違っています。 Hit@5が0.374ということは、こうした質問の62.6%で正しいコミットが上位5件に含まれていないということです。それらのケースでは他のどの選択肢よりも優れていますが、それでも大半で失敗します。結果は検証すべき手がかりとして扱い、git showで確認してください。確定した事実として扱ってはいけません。
通常の Git を使う場合
Git Why は、セマンティックインデックスに対するランキング検索です。用途によっては適切なツールではありません。その場合は、すでに適切なツールが Git に用意されています。
- 正確な文字列がわかっている場合。
git log -Sとgit log -Gは網羅的に検索します。ここでのキーワードモードはランキング検索であり、網羅的ではありません。 - 網羅的に検索する場合。 チェックアウトに対して
ripgrepを使うか、git grepを使います。 - 因果関係を検証する場合。 類似性は時系列ではありません。
git merge-base、git log --ancestry-path、git showを使って祖先関係を確認してください。
Git Why は、何が起きたかは覚えているものの、それが何と呼ばれていたかを思い出せない場合に使います。
詳細情報
- ドキュメントサイト — インストール手順、検索の仕組み、CLI リファレンス、FAQ を案内します。
ROADMAP.md— プルリクエスト、gh why、Wiki、および公開前に測定が必要な項目について説明します。docs/embedding.md— 測定した 9 種類の埋め込みモデル、オプトイン可能な +41% のモデル、デフォルトを変更しなかった理由について説明します。docs/daemon.md— オプションのデーモンについて説明します。常に準備しておく内容、検索を妨げることが決してない理由、セキュリティ方針を記載しています。docs/indexes.md— インデックスの保存場所、ワークツリー、サブモジュール、モノレポ、ディスク使用量、共有モデルキャッシュについて説明します。docs/examples.md— 実際のリポジトリでの実際の出力を紹介します。このツールが適切でないケースも含みます。docs/plugin.md— 2 つのプラグイン、MCP ツール、スキル、およびフックがない理由について説明します。docs/decisions.md— 試したものの採用しなかった方法を、測定結果とともに紹介します。うまくいかなかった 7 つの最適化について説明します。docs/install.md— インストール方法とアンインストール方法をすべて説明します。インデックスとモデルキャッシュのディスク上の保存場所も記載しています。docs/operations.md— 耐久性、並行処理、終了コード、履歴の対象範囲、カバレッジの制限など、運用上の契約をすべて説明します。docs/report.md— この README の数値の出典となるベンチマークレポートです。docs/spec.md— 本プロジェクトの実装時に準拠したビルド仕様です。ソースコードのコメントから該当セクションを参照しているため、ユーザー向けドキュメントではなく、由来を示す資料として保持しています。
開発
mise setup # install dependencies, then doctor
mise check # format, lint, typecheck, protocol hash, unit tests
mise test:integration # real repositories, real storage, real locks
mise test:package # pack, install into a clean prefix, invoke through Git
mise site:build # build the docs/marketing site in site/
mise tasks # everything else, including every benchmark
README.md、site/index.md、docs/report.md の数値は、実行時の生データから bench/report.mjs が生成します。手作業で編集すると CI が失敗します。man ページ、サイトの CLI リファレンス、3 種類すべてのシェル補完は、フラグの定義元である唯一の場所、git why -h と照合して確認されます。
モジュールの担当範囲とリリースの作成方法については、docs/contributing.md を参照してください。
ライセンス
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。