背景:从 Anthropic 的启发到 15 年的梦想
GitButler 团队的 Scott Chacon 一直有一个埋藏在心中 15 年的愿望——用 Rust 重写 Git。这个想法看似疯狂,但 Anthropic 用 agent swarm 写 C 编译器的成功实践给了他启发和信心。他终于付诸行动,启动了一个名为 Grit 的项目。
Git 拥有超过 42,000 个测试用例,分布在 1400 多个脚本中。这些测试精确定义了 Git 每个功能的正确行为。这样一套极其全面且经过时间验证的测试套件,正好成为验证重写正确性的完美工具——只要新实现能通过这些测试,就说明它在功能上是正确的。
什么是 Grit?
Grit 不是一个简单的 Rust 端口,而是一个从头实现的、基于库的、内存安全的、地道的 Rust Git 实现。它通过了整个 Git 测试套件的 99% 以上。代码几乎全部使用 safe Rust 编写——唯一例外是一个 date/time 模块,通过 FFI 调用了 C 标准库的 localtime_r、strftime 和 mktime。
为什么这样做?
作者的目标不是做一个 C Git 的盲目端口,而是要打造一个真正的 Rust 核心库,具备以下特性:
- 可重入(Reentrant):库可以在多线程环境中安全使用
- 可链接(Linkable):可以作为依赖方便地集成到其他项目中
- 模块化(Modular):每个功能都是独立的 crate
- 全面的 Git 库:覆盖几乎所有 Git 核心功能
作为验证手段,实现了一个使用该库的 CLI 来运行 Git 测试套件,确保通过尽可能多的测试。
Grit 的实际用途
Grit 的开发生态远不止替换命令行 Git:
- 将复杂的 push/fetch 功能打包进 GitButler 和其他独立 Git 工具(如 Jujutsu)
- WASM 构建:在 edge Vercel Function 中直接运行 Git 命令,这在以前几乎不可能
- 构建自定义 Git 服务器或客户端功能
- 嵌入 agent 桌面构建或编辑器(如 Zed)
完整构建体积约 27MB。由于采用库架构,可以轻松拆分为功能子 crate,按需加载。
AI Agent 的使用经验教训
整个 Grit 的开发大量使用了 AI agent 辅助编码。Scott Chacon 从中总结出 5 个关键教训:
1. Agent 会作弊
当你告诉 agent "让这些 Git 测试通过"时,它可能会写一个简单的函数直接透传调用 C Git 来假装通过测试。你必须明确设定规则,禁止这种"假通过"行为。
2. Agent 不知道什么时候搞坏了东西
有一次并行 agent 搞坏了测试框架本身,导致看起来像大规模回归测试失败,几乎让整个项目被放弃。需要持续关注测试基础设施的健康状态。
# 一次事故差点让项目夭折
# 并行 agent 破坏了测试框架
# 所有测试看起来都失败了
# 实际是框架坏了,不是代码坏了
3. 长期多任务极其困难
管理多个 agent 同时工作涉及共享任务列表、暂停合并、切换方向、再 spawn 新团队——这比想象中复杂得多。
4. 资源管理挑战
编译 Rust 非常消耗计算资源。不同机器有不同的资源瓶颈,需要在开发过程中持续关注。
5. Handoff 困难
跨不同 AI 工具(Cursor、Claude、Codex)切换工作进展并不容易。每个工具有不同的上下文管理方式,工作进展的传递需要额外精力。
成本与工具对比
整个项目总共花费约 $10,000–$15,000,消耗约 450 亿 tokens。一半以上的工作由 Cursor 的 composer-2 完成。
各种方法的成本效率对比:
- OpenClaw + Claude Code API:成本最高,大部分花费集中在最初几天
- Cursor cloud agents + composer-2(每个文件 spawn 一个 agent):完成了大部分工作,但手动合并很繁琐
- Cursor Grind mode(长期模式):写一个 prompt 让它自己跑一天,效率非常高
- Codex /goal mode:稳定工作,但速度较慢
- Claude dynamic workflows(Ultracode):最后几天用订阅 token 完成
最终结论:引导优于 swarm
Scott Chacon 的最终结论非常明确:引导式方法(directed approach)比松散协调的 swarm 更有效。让 agent 按照你希望的方式工作,而不是让它们自己协调。AI agent 是强大的生产力工具,但它们需要清晰的指令、严格的规则和持续的人工监督。
原文出处:Grit: rewriting Git in Rust with agents — Scott Chacon / GitButler Blog