Agent 每天合入三万次代码,git 为什么撑不住了?

📅 发布时间:2026/10/15 19:14:27
Agent 每天合入三万次代码,git 为什么撑不住了?
Agent 每天合入三万次代码git 为什么撑不住了一、一个反常的瓶颈一家公司里写代码这件事突然不再慢了。五个月前Anthropic 平均每天合入 2500 次代码变更。到九月这个数字是 30000 次以上。增长超过十倍而团队没有扩编十倍。正常的故事到这里应该讲「产能爆炸」。但真正的故事从下一步开始代码写完了卡住的地方变成了把代码合进去。构建、CI、版本控制——这些过去二十年为人类规模设计的工具开始一个接一个地冒烟。Anthropic 的工程博客在 10 月 13 日发了长文把整个过程摊开讲了他们花了五个月自研了一套版本控制系统 Scion把一个单体仓库整体从 git 迁走。原文见 Redesigning source control at Anthropic。这不是一条「git 已死」的新闻。恰恰相反它更像一次压力测试当代码的主要生产者从人变成 Agent哪些默认假设会先碎。二、先看数字讨论架构之前得先感受一下这套仓库到底有多大。主干分支的历史单独就接近 100 GB压缩后的工作副本超过 25 GB。为了 CI他们每天要执行大约 2500 万次代码检出——这还没算开发环境、Agent 沙箱和研究任务。如果每次检出都天真地拉完整仓库一天的 git 流量会超过 600 PB。他们不是没试过常规解法。浅克隆、稀疏检出、promisor 远端全部用过。仓库镜像和对象存储里的快照种子seeds也上了——峰值时他们维护着几百个内部 git 镜像靠这套东西硬扛。镜像确实买到了时间但代价随合入量一起涨。种子刷新之间离主干越来越远依赖历史的操作diff、blame在部分克隆上越来越难保持正确。维护几个镜像不难维护几百个是另一回事。三、碎裂的是设计前提Anthropic 的复盘里有一句很关键的判断他们把 git 当集中式系统用因为只有一份权威副本但几乎所有客户端都是 Agent 和任务它们天然在线。而 git 的核心设计是去中心化每个克隆都是一个自包含的完整仓库离线也能算 diff、读历史、看 blame、切换任意版本。对绝大多数仓库这是正确的设计也是 git 成为标准的原因。问题在于当我们给一个单体仓库挂上几百万次在线调用时这套优点的成本被放大了为了「离线也能工作」每个客户端都要付出完整仓库的代价。这也是 packfilegit 压缩对象包成为负担的原因——包越大协商越贵单次响应越大缓存越难做。参考坐标不是没有。Google 的 Piper 和 Meta 的 Sapling 都是这个方向的前例只是它们没有公开到这个细节程度。四、Scion 的五条原则他们先把假设写下来再动代码。客户端始终在线。服务器永远可达客户端按需取数据不再假设离线自足。客户端与服务端不对称。在 git 里每个客户端都有能力当服务器。在 Scion 里回答文件历史与 blame、创建提交、执行合并变基全部由服务端做客户端只维护一个有上限的本地对象缓存负责把文件铺到磁盘、监听文件变化。客户端算得很少因此本地需要的数据也少得多。查询本身要能被程序调用。过去一个 CI 任务想问「这一行最后是谁改的」得先养一个本地仓库。Scion 把客户端用的所有查询都开成 API于是自动 bisect、自动 revert 这类流水线才真正跑得起来。所有组件必须水平扩展。仓库数据是分布式的服务端也没有完整物化副本没有 packfile也就不需要仓库维护窗口。提交必须便宜、增量、无锁。每次提交、变基、合并都在服务端发生所以没有 push 这一步但代价是这些操作必须快——创建提交和更新下游数据结构的成本要随变更大小增长而不是随仓库大小增长。他们还刻意不用 ref分支、标签这类全局指针只保留主干和发布分支因为「所有服务器必须达成一致的全局状态」就是下一个扩展瓶颈。五、一层层缓存把 git 镜像换成服务落到实现上Scion 的基本单位叫 changeset写进预写日志的一条记录。git 提交存的是指向 tree 的指针changeset 存的是「相对第一个父提交变了哪些文件」加上内容寻址、指向对象存储里压缩内容的指针。changeset 由服务端创建立刻全局可见。因为只记录变化changeset 自己答不出 blame 和历史问题。答案靠派生数据文件 blame 结构、路径历史、提交图的跳表。每类派生数据按递归定义——某个 changeset 上的取值由它各父提交上的取值算出。好处有三条加新索引很容易可以选即时算还是延后算客户端看不到内部结构结构可以随便改。后来他们按需加了副本检测索引、路径搜索索引客户端一行没动。分层也很直白节点上的守护进程scion-daemon为整台机器缓存对象起点是周期性刷新的快照区域内的scion-cache直接从内存里按客户端要的磁盘格式流式发送对象不做差量压缩权威的scion-server按需读 Spanner 或对象存储。三层的 RPC 完全一致客户端不需要知道缓存的拓扑。但分层被强制隔离——区域缓存挂了不能把上游拖下水。结果是一串很干净的数字每层缓存命中率 99% 以上整套 Scion 的 CPU 和内存占用是原来 git 镜像基础设施的 200 倍之小CI 和研究任务检出代码快了两个数量级秒级而非分钟级光是 CI 就省下 25% 的 CPU 容量。顺带一提Scion 的取数协商和 git 的 fetch 完全不同它不告诉服务器「我有什么」而是直接基于 tree 和 blob 递归地要「我要什么」。每个请求针对的都是永不变更的对象所以任何一层缓存都能答结构上就是传统的多级缓存也因为没有几 GB 的 packfile 响应过程天然可续传。六、七个人五个月和一句「不行」这套系统——Scion、代码评审工具 Antique外加半打相关系统以及完整的仓库迁移——由一个七人小组完成耗时五个月期间每天合入的代码量还涨了十倍。Claude 在里面扮演了很重的角色。有一个例子特别能说明问题他们早先手写了一个 git 到 Scion 的摄取管道原型自己觉得还行。拿到 Claude Mythos Preview 的内部快照后他们让模型重写一遍——没有任何额外说明新版内存占用少 20 倍、速度快 4 倍同时保持了所有关于摄取顺序和数据结构的隐式约束。但文章里更值得抄的一段是工程师角色的变化。所有参与这套系统的工程师都承认Claude 写代码比他们强。他们提供的是另一类东西对系统之间高层组件的理解以及设计层面的取舍。原话说很多时候工程师的作用是对 Claude 说「不行」。举的例子很具体。迁移期间有多个系统试图用「线性读取提交日志」来查一个变更何时合入主干而不是去问评审工具——这是一种为了满足某个本就不该存在的模式而违反核心约束的做法。另一个方向是过度防御有一次对抗式评审过于不信任另一个内部服务Claude 于是加了一堆多余的校验和复杂度。工程师仍然评审每一个变更申请但看的是意图而不是逐行读代码。运维上也有一点新东西他们给每个组件建了一个 Slack 频道让 Claude 盯着单个组件的健康度叫「superfans」。有 scion-daemon superfan、scion-cache superfan、Antique 合并队列 superfan。这些 Agent 能读到遥测和日志去找那些传统告警看不见的细微异常。七、争议也一样真实Hacker News 上这条讨论有 750 多条评论讨论帖反对意见相当集中。第一条是本地提交的自由。git 甚至更激进的 jj 的整个论点是你能在本地堆出一串小提交随便重排、合并、丢弃最后再决定推什么。Scion 把提交、变基、合并全放到服务端这部分空间就没有了。第二条是对「没人看代码」的警觉。文章里的说法是团队评审每个变更的意图而非逐行也承认 CI 会放行并发变更导致的冲突靠 Claude 事后修。有评论直接问这是不是意味着生产环境上线的是没有人工逐行审过的代码。第三条是那个 600 PB 的数字本身。有评论质疑真的每天有这么多代码需要改吗另一条高赞回复则换个角度——如果模型真这么好用那把 prompt 当源码提交、把生成的代码当成昂贵的构建产物放进仓库是不是更合理的工作流。Anthropic 自己也划了边界Scion 不适合替代通用场景下的 git这套思路只在「数万工程师或大群 Agent 疯狂写代码」的超大单体仓库里成立。他们甚至说把它做成给所有人用的公共产品很难所以更实际的做法是公开思路让 git 生态自己吸收其中可用的部分——比如服务端不必照着客户端的样子做git 平台可以提供更完整的服务端 RPC。八、留给工程实践的三条瓶颈会转移而且往往转移到你最信任的那一层。这次是版本控制。下次可能是构建缓存、制品仓库、测试调度——判断标准很简单这个工具的设计假设里有没有「客户端是人、带宽稀缺、离线可用」这类前提。镜像和缓存不是架构是止疼药。从几十个镜像涨到几百个的时候问题已经不是运维熟练度而是数据模型选错了。Scion 最狠的一步是取消了「完整副本」这个概念本身。Agent 时代的工程能力前半段是提出好问题后半段是说「不行」。生成代码已经便宜到不再是约束值钱的是系统边界、数据模型和「这个防御不该加」的判断。原文https://www.anthropic.com/engineering/redesigning-source-control参考Sapling、git 部分克隆文档、HN 讨论