mcpField
G
Git Why

Git Why

本地服务
alliecatowo.github.io版本控制05 天前更新

关于 Git Why

Git Why 是面向开发者和编码 Agent 的本地优先 Git 历史搜索工具,可按问题语义和全文查找相关提交。它返回提交、作者原文和相关差异作为证据,而不自行生成原因解释。

主要功能

  1. 01语义与全文搜索 Git 历史
  2. 02展示提交、作者原文和差异
  3. 03增量建立仓库索引
  4. 04提供可选常驻索引服务
  5. 05支持 MCP 与 Agent 插件

适用场景

  1. 01记得问题但想不起提交关键词时查找历史
  2. 02查看某项代码改动的提交证据
  3. 03将历史检索接入 Agent 工作流

MCP 相关

它提供 MCP 服务,可由 `npx -y @alliecatowo/git-why mcp` 启动,向 MCP 客户端提供 Git 历史检索。项目还提供包含该服务的 Agent 插件。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"alliecatowo-git-why": {
"command": "npx",
"args": [
"-y",
"@alliecatowo/git-why"
]
}
}
}
启动命令npx -y @alliecatowo/git-why

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
npm@alliecatowo/git-why0.2.0

工具

2

收录的工具列表 · 更新于 2 周前

参数类型必填说明
cwdstring否仓库目录。默认为服务器进程目录。
modeenum否hybrid | text | semantic
sortenum否relevance | oldest | newest
limitnumber否
querystring是用自然语言表述的问题。例如:“为什么放弃前要重试两次?”、“那个重复发送 webhook 的 bug 是怎么回事?”描述症状或决策,而不是文件——`git log -- <path>` 已能搜索文件,而且效果更好。
groupsarray否按提交级 RRF 融合的其他查询组。
ownersboolean否同时返回建立此领域的人员,按其提交的相关性排序,而非按仍存留的代码行数(git blame)或提交次数(git shortlog)排序。适用于“谁构建了这个”、“谁应该审核这个”、“谁了解这个”等问题。
temporalobject否可选的时间检索约束。省略时由 CLI 执行查询拆解。
temporal.typeenum否first | last | removed | changed_when | before | after | between | around | timeline
temporal.anchorstring否
temporal.anchorEndstring否

详细介绍

Git Why

License: Apache-2.0 Node.js >= 22.12 CI

git blame 会告诉你是谁修改了代码。git why 会找出能解释这些修改的历史记录。

在 Git 历史记录中进行本地优先的语义搜索和全文搜索。它会返回实际提交、作者的原话,以及相关差异。它检索证据,不会自行生成解释。

以下是 mise run demo 的实际输出。该命令会根据 bench/fixtures/demo/build.mjs 重建一个小型示例仓库,并对其运行以下两个查询。这里的内容并非手工编写,你可以用一条命令重现。

如需查看真实仓库(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 可查看索引是否为最新。

与 Agent 搭配使用

plugins/ 中提供了两个插件:

插件功能
git-whyMCP 服务、路由技能和索引管理技能。
git-why-full同上,另含用于搜索当前代码的 zg,以及一个用于处理需要多次搜索的问题的历史探索 Agent。

OpenCode 用户可使用 opencode/,其中包含带有 MCP 注册信息的 opencode.json 和一段 AGENTS.md 配置。

该技能实际教会 Agent 的是何时不该查阅历史记录。如果能说出符号名称,它会告诉 Agent 使用 git log -S,因为在这种情况下,该工具的表现明显较差(Hit@10 为 0.950,而它为 0.350);对于代码的当前状态,则应使用代码搜索,而不是查阅历史记录。声称自身工具总是最佳选择的技能,只会让 Agent 更难胜任工作。

其他任何 MCP 客户端都可以直接运行该服务:npx -y @alliecatowo/git-why mcp(安装后也可以运行 git why mcp)。它也已作为 io.github.alliecatowo/git-why 收录于 MCP 注册表。

请参阅docs/plugin.md。

提升速度(可选)

git why server on

该守护进程会在多次查询之间保持索引、嵌入模型和血缘表处于打开状态。在包含 30,000 次提交的 curl 仓库中,每次查询耗时可从 569 ms 降至 286 ms。守护进程运行后,搜索会自动使用它。

搜索绝不会因守护进程而失败:如果守护进程未运行、无法访问,或索引在其运行期间被移动,查询就会改为直接运行。--daemon=direct 可选择不使用守护进程,--daemon=server 则要求守护进程正在运行。请参阅docs/daemon.md。

原因

git log --grep 只能匹配你已经知道的词。代码改动的原因通常写在提交消息中,但你很少记得它的确切措辞——几个月后,你记得的是自己话语中的那个_问题_。

再看看上面的第一个示例:查询是“reconnecting subscribed twice”,提交标题是“Stop duplicate subscriptions after reconnect”。两者几乎没有共同词汇。这并非 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@1Hit@5MRR无结果
git why0.2010.3740.2660
zg(语义代码搜索)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

比 zg 高 10.2 倍,比最佳 Git 原生策略高 23 倍——而且这是唯一一种几乎能回答所有问题,而不是返回空结果集的方法。

表现较差的场景

如果你能说出符号名称,就改用 pickaxe 搜索。对于跨文件因果问题,git log -S 的 Hit@10 得分为 0.950,而 git why 为 0.350。对于你能提供确切字面内容的工具,语义搜索并无优势。

这就是诚实的适用范围,已发布的 技能会告诉 Agent 这两个方面:

  • 说不出术语 → git why
  • 说得出术语 → git log -S
  • 查当前代码,而非历史 → zg
规模与成本
它能帮助 Agent 吗?

检索质量不是产品本身。关键在于:Agent 回答真实问题时,借助工具是否能答得更准确,或减少交互轮数。针对同一组冻结任务设置了四组实验,每项任务均进行配对,并根据提供方自己的计量数据库核对 token 数量。

模型配对样本数准确率胜-负节省的工具调用中位数
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-0多 0.5

不同模型的结果不一。每个模型的配对样本数都只有个位数,因此这些结果仅作描述,不具统计显著性;我们有意如实报告这一点——趋势一致,但效果幅度尚未确定。完整方法和各组数据见基准测试报告。

方法、各组数据和预注册假设: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 on384 ms p50,491 ms p95
无守护进程时执行相同查询851 ms p50,1371 ms p95
差异/证据摄取,真实代码库消融测试值得投入,ΔHit@5 +0.375
哪些有效,哪些无效

共实现并测量了八项优化,只有一项通过验证。

有效的那一项:计算问题与提交自身说明之间的词汇重叠度,并在比结果列表更深的候选池中重新排序。权重在开发集的一半上选定,再在留出的一半上评估一次——在从未见过的样本上,MRR 提升了 26%,Hit@1 提升了 44%。已发布。

其余七项均无效:针对散文调优的嵌入模型、伪相关反馈、散文式提交惩罚、调用方重述查询、扩大结果窗口、结构扩展和短语融合。它们都没有改善 MRR。

起作用的不是更好的想法,而是换了一个问题。那七项都在问“这样排序是否更好”。有效的那项则先问:正确的提交究竟在哪里?结果发现,语料库中有四分之一已被检索到,但排名低于第 5 位,这是重排问题;而有 42% 根本没有被检索到,这并非重排问题。详见 docs/decisions.md。

剩余的提升空间就在这 42% 上:这是嵌入模型本身的召回率问题。现在我们测量了它,而不再凭空猜测—— docs/embedding.md 在固定候选池上比较了十种模型。Transformer 嵌入模型的 MRR 分别比已发布的静态模型高 41%(jina-v2-small)和 64%(jina-v2-base),但索引耗时分别是其 191 倍和 1287 倍,还需要 ONNX 运行时。两者均可选择启用;默认方案仍保持快速且无依赖,因为一个只需几秒即可安装、不到一分钟即可完成索引的工具,不应悄然变成一个需要十五小时才能完成索引的工具。

而且它大多数时候都是错的。 Hit@5 为 0.374,意味着对于这些问题,62.6% 的情况下正确提交不在前五名之内。尽管在这些问题上它仍胜过所有其他方案,但大多数时候还是会失败。应将结果视为有待通过 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 参考和常见问题解答。
  • ROADMAP.md — 拉取请求、gh why、wiki,以及这些功能发布前需要进行哪些衡量。
  • docs/embedding.md — 对 9 种嵌入模型的测评、可选启用且效果提升 41% 的模型,以及默认模型为何没有改变。
  • docs/daemon.md — 可选守护进程:它会预热哪些内容、为何绝不会导致搜索失败,以及其安全状况。
  • docs/indexes.md — 索引的存放位置、工作树、子模块、单体仓库、磁盘占用和共享模型缓存。
  • docs/examples.md — 在真实仓库中的实际输出,包括一个不适合使用此工具的案例。
  • docs/plugin.md — 两个插件、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 就会失败。手册页、网站的 CLI 参考以及全部 3 种 Shell 补全都会根据 git why -h 进行检查;标志集仅在此处定义。

有关模块职责归属和如何发布版本,请参阅 docs/contributing.md。

许可证

Apache-2.0。请参阅 LICENSE 和 NOTICE。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。