互联网

Anthropic 用 AI 五个月自研版本控制系统,把日合并量从 2500 提到 30000

来源:Anthropic    作者:Anthropic      2026年10月15日 14:19

导语:Anthropic 在其工程博客披露,公司日均合并代码量从 2026 年 5 月的约 2500 次跃升到 9 月的 30000 次以上,git 已成最大瓶颈。

摘要

Anthropic 在其工程博客披露,过去几个月公司日均合并代码量从 2026 年 5 月的约 2500 次跃升到 9 月的 30000 次以上,git 已成最大瓶颈。团队历时五个月自研并完整切换到一套内部版本控制系统 Scion,同时配套重写了代码评审(Antique)、代码搜索、IAM 与大规模落地代码的工作机制。基础设施在 CPU 和内存占用上比原先的 git 镜像体系缩小约 200 倍,CI 与研究任务的代码检出时间从分钟级压到秒级,单是 CI 就拿下 25% 的 CPU 容量收益。Anthropic 把这次迁移视为「AI 规模下的软件工程」样本,并强调 Scion 并不打算替代 git 在通用场景里的角色。

正文(译文)

 随着每天合并次数增长超过十倍,源代码管理成了我们最大的开发瓶颈。这里分享我们如何在五个月内迁到一套内部版本控制系统。

在 Anthropic,写代码本身已不再是构建系统或做研究的瓶颈。Claude 能自主地迭代研究循环,对复杂程序做微观级优化,并以前所未有的速度和规模从零搭建新服务。当前的瓶颈,是当初按「人」的规模设计的整套研发基础设施:源代码管理、构建与 CI。

2026 年 5 月,Anthropic 平均每天合并约 2500 个代码改动;到 9 月,我们每天合并量超过 30000 个。我们并不预期这种增长速度会很快放缓——可合并代码的潜在需求几乎无穷,每解开一个瓶颈都立刻带来代码产量的进一步攀升。

为了承接这种增长,我们自研了一套版本控制系统 Scion,并在五个月内把主仓库从 git 完整迁出。我们也在同一时间段里上线了代码评审界面(Antique)、代码搜索、源代码管理 IAM、一套用于托管和落地大量代码的全新机制,等等。本文聚焦 Scion 的构建本身。它的价值在于:Claude 写代码的能力既是我们陷入这种局面的原因,也是我们能快速构建出一套高质量、可扩展系统去应对它的原因。

在展开我们做了什么之前,需要先承认我们的工作负载有多不寻常。Anthropic 在用 Claude 写软件这件事上几乎是所有公司里最激进的,所以我们最早撞上「按人规模设计的工具开始吃紧」并不意外。源代码管理只是其中一个。虽然我们不认为大多数组织在短期内会遇到同样的问题,但我们判断其他重度使用 AI 编程工具的团队很快也会摸到同样的天花板,这正是我们想把构建过程与教训分享出来的原因。

git 是一套去中心化的系统:每个克隆都是一份完整、自包含的仓库,能离线计算差异、读取历史与 blame,并检出任意历史版本。对绝大多数仓库来说这是正确设计,也是它成为标准的根本原因。

随着主仓库变大,它越来越不再适合这套设计。我们的主分支历史就接近 100 GB,工作副本超过 25 GB。我们每天要为 CI 拉起约 2500 万次代码检出,这还没算研发环境、agent 沙箱和研究任务。如果按 git 原始方式拉取,这意味着每天会产生 600 PB 以上的 git 流量。

git 提供了一些工具来操作仓库的一部分,比如浅克隆、稀疏检出、promisor 远程仓库。除此之外还有一些常见的大仓库工程手段,比如内部 git 镜像、放在对象存储里的仓库快照(seeds)。我们全都用过——峰值时段运行着数百个内部 git 镜像来扛住负载。这给我们续了命,但随着合并速率上升,这些机制越来越难管了:seeds 离主分支 tip 越来越远,依赖历史信息的 diff、blame 这类操作在部分克隆上也越来越难保证正确性。

退一步讲,我们意识到——像大多数公司一样——我们其实是在把它当成集中式系统跑,只有一份权威副本,而我们的客户端几乎全是必然在线的 agent 和 job。让 git 在分布式、离线场景下表现优异的那些特性,正在成为仓库变大后扩展性的反向拖累。我们于是问自己:如果从一开始就知道客户端必然在线,那版本管理应该长什么样?

随着 agentic 编码的普及,很多关于软件开发流程的常识在被改写。我们在构建 Scion 时接受了这些变化,这让 Scion 在几个核心原则上与 git 走了一条根本不同的路。巨型 monorepo 的版本控制不是没有先例,Google 的 Piper/Piper 等是重要参照,让我们能在前人经验之上构建 Scion。我们的核心原则如下:

客户端几乎全是 agent 和 job,因此我们假设服务端永远可达,让客户端按需拉取数据。Scion 的客户端和协议都围绕这一前提设计。

git 里每个客户端都能成为完整的服务器。Scion 则由服务端负责文件历史与 blame、创建 commit、执行 merge 与 rebase 等所有相关操作。客户端只维护一份有界的本地对象缓存,把工作目录文件落到磁盘,监听文件系统变更,并给用户一个顺手的工作面。它能算的东西很少,代价是本地所需的数据量大幅下降。

一个全面的版本控制服务可以支撑大量新形态应用。在 git 体系下,CI 任务或工具若想知道仓库里某个问题(比如某一行最后谁改的、两个 commit 之间的关系),要么得自己维护一份本地副本,要么寄希望于厂商 API 提供。Scion 把客户端用到的所有版本控制查询都通过 API 暴露出来,许多场景下任务再也不需要本地仓库。我们很多内部工具——比如自动 bisect 与 revert 流水线——没有这种廉价、可编程的版本控制接口就无法规模化。

我们曾运行过数百个 git 镜像,对容量压力极大;仓库大到镜像的磁盘或内存撑不住时这套方案就失效了。Scion 把仓库数据分布式存储,每个组件独立横向扩展;即使在服务端也没有任何一个完整的、完整物化的副本。没有 packfile 之类的概念,因此不需要任何仓库维护工作。

在 git 里,本地提交后再 push 才能共享。在 Scion 里,commit、rebase、merge 全部在服务端发生,所以没有 push 这一步,但每个操作都要快。创建一个 commit 并更新其下游数据结构的成本必须按改动的规模来扩展,而不是仓库整体规模,否则服务端撑不住。Scion 的开发循环刻意少用 ref(指向 commit 的指针),只用主 ref 与发布分支——因为需要让所有服务端达成一致的状态是规模隐患。

因为我们的 monorepo 实在太大,每天又要做几千万次代码检出,所以我们尽量避免检出。Scion 中,CI 任务想知道 commit 与 merge base 之间的 diff,可以直接问服务端。写入也是同理:很多写入型负载可以完全跳过 checkout、纯 API 完成。Scion 的协议围绕稀疏检出展开——只包含客户端请求的目录;虚拟化检出按需物化文件,任务要哪部分文件就付哪部分成本。

把这些原则在工程实践中落地,对理解 Scion 的形态最有帮助。这些思路同样适用于其他版本控制系统,乃至软件研发流程的其他环节。

Scion 中工作的基本单位叫 changeset——预写日志(write-ahead log)里的一条记录。changeset 包含 git commit 该有的绝大多数信息。但 git commit 存的是对 tree 的指针,Scion 的 changeset 存的是相对于其第一父节点的改动文件清单,外加指向压缩文件内容的内容寻址指针,存放在 blob 存储里。changeset 在服务端创建,立即对全网可见。

这一结构让我们能用极高吞吐接收 changeset——没有 packfile 要接收,没有锁,没有跨服务器协调,也没有 ref 要来回挪。Scion 技术上支持 ref,但因为创建和拉取 commit 都不涉及 ref,移动 ref 是一次性对一行 Spanner 做 CAS,与 changeset 创建解耦。

changeset 只记录改了什么,单凭它没法快速回答「这行最后谁改的」「哪些 commit 动过这个文件」这种问题。要回答这些,Scion 会在 changeset 之上再建一层数据结构,包括文件 blame、路径历史,以及 commit 图的跳表(skip list)。我们把所有不是 changeset 本身的数据叫「派生数据」,并用统一的机制来算。每种派生数据递归定义:它的值由其父节点的同类值计算出来。

这个机制带来三方面收益。第一,需要加快时随时能加新类型的派生数据。第二,对每一种类型都可以选 eager 算还是 deferred 算,避免物化不需要的数据。第三,客户端从不接触这些数据结构内部,我们优化它们时不用动客户端。系统演进过程中我们多次新增派生数据类型,比如复制识别或基于路径的文件搜索的新索引。

一台小型 Scion 服务集群就足以覆盖客户端可能需要的版本控制操作——拉取 changeset、计算 diff、找 merge base、抓取 blob 等。所有版本控制数据都做内容寻址,数据一旦写入就不再变化,任何服务端都可以独立缓存它们。因此服务器是横向扩展的、几乎不需要协调。它们本质上是大缓存,能顺手计算派生数据并把结果回写 Spanner。

Scion 的众多消费方不再需要各自维护本地仓库。原先获取和维护仓库对 CI 任务或那些需要问版本控制问题的工具来说是个很大的负担,尤其是 commit 血缘和 blame。在迁移早期——还没有自己的客户端、仓库格式与协议之前——Scion 只回答这些「元数据」类问题。拉取文件内容、物化工作副本才是真正吃数据的操作,需要单独设计。

Scion 的 scn 客户端在多个关键点上脱离了 git 的 fetch 协议,因此能以高扩展架构运行,对服务端 CPU 的需求显著低于 git 服务端。Scion 的协商不让服务端知道客户端已有什么;它完全围绕客户端想要的 tree 和 blob 工作。客户端从根 tree 开始检查本地缺哪些 tree,并递归请求,然后对 blob 做同样处理。每个请求都是对一个不再变化的对象,任何缓存都能回答,整个架构贴近传统的分层缓存。这个过程也是可恢复的——因为不会有单条多 GB 的 packfile 响应。稀疏甚至虚拟化检出也无需特殊支持,因为客户端不请求它不想要的 tree。

集群里,客户端通过 socket 跟守护进程 scion-daemon 通信,后者缓存整机的对象。绝大多数节点都需要 monorepo,同一节点上的 job 大部分对象可复用。每个守护进程以周期性刷新的快照起步,再只与本区域的 tree 和 blob 缓存服务器(scion-cache)通信。这些缓存服务器直接从内存中按 daemon 将消费的磁盘格式流出对象,因此不需要花时间计算缺失对象或做 delta 压缩。缓存层缺失对象时,向上游的权威 scion-servers 拉取,后者按需从 Spanner 或云存储读取。

scion-daemon、scion-cache 和 scion-server 对该协议响应同一套 RPC,客户端无需关心缓存拓扑。任何一层理论上都可以跟另一层通信,但我们严格限制层级以隔离故障域——避免区域 scion-cache 故障压垮上游 scion-servers,进而拖垮整套系统。

每一层的缓存命中率都维持在 99% 以上、并且不需要长期保留状态,因此需要时扩容容易。我们的 Scion 基础设施占用的 CPU 与内存规模是此前 git 镜像体系的约 1/200。CI 与研究任务的代码检出快两个数量级(从分钟级压到秒级),让机群空闲出可观算力,单 CI 一项就释放了 25% 的 CPU 容量。客户端和缓存都不需要仓库维护,让 job 的生命周期管理更简单。

这里有一个格外突出的例子。今年早些时候,我们还基本靠人工手写了第一版 git-to-Scion 的导入流水线原型。我们觉得已经不错了——直到拿到 Claude Mythos Preview 的内部早期快照。我们请它把整套系统重写,没有任何额外提示,产出的版本内存占用降为原来的 1/20、速度快 4 倍,同时保留了所有关于导入顺序与数据结构的隐式不变量。

构建与运营 Scion 的过程给我们上了几堂关于「AI 规模软件研发会长什么样」的课。

Antique(我们的代码评审工具,光它就够再写一整篇博客)以及与之相关的六七个系统,全部建出来并完成主仓库迁移,期间日合并量增长了 10 倍。过去,开发、交付这样一套版本控制系统需要一家公司以年计的时间反复迁移、需要多得多的人手。我们认为这种快速、敏捷的迁移方式未来会变得更常见。

参与构建这套系统的工程师如今普遍认为 Claude 在编写代码这件事上比自己更强。但工程师仍然提供了无可替代的高层系统认知与设计层面的判断——知道要解决什么问题、要做到什么规模。多数时候,我们发现工程师的工作其实是跟 Claude 说「不」。Agent 有时会为了凑一个本就不该被允许的模式,违反系统的核心约束。这一点在迁移过程中尤其常见。比如有几个系统原本该通过代码评审工具来查一个改动何时合并到 main,结果却绕过去线性扫描 commit 日志。Anthropic 也在大量使用对抗式评审(adversarial review),虽然它在很多场景下很有效,但也容易陷入短视,于是有经验的工程师需要引导 Claude,避免它在应对假想中的威胁时过度设计。例如有一次评审对信任另一个内部服务这件事过度防御,导致 Claude 加进过多校验和复杂度。我们的团队成员仍然会审每一笔改动,只是现在他们审视的是———Claude 的代码与人写的代码水平相当并做出相应调整。

由于 Claude 能以比我们快得多的速度写出巨量代码,Scion 也成了我们打过的所有代码库里测试最充分、防线最严密的一套。即便时间紧,我们仍能为我们遇到过的每一个非平凡的基础设施与版本控制交互构建密封型模拟(hermetic simulation),并加上模糊测试与复杂的速率限制。Claude 顺手就找到了多处重要优化——比如针对祖先查询的一个算法优化,绕过了我们一个索引——这种活通常需要专家花几天甚至几周去分析和调优……而且第二天它又复现了一次。

在巨型 monorepo 中管理安全、合规与权限,与管理规模同等重要。我们从一开始就把这些放进设计。Scion 支持仓库级的细粒度访问控制,也能把权限下到单个目录——在保留 monorepo 收益的同时保护最敏感的代码。我们搭的代码评审工具还能表达复杂的审批语义约束,把仅改注释的提交与改动关键业务逻辑的提交区别开来,让人工评审把精力放在最关键的改动上。

团队重度使用 Claude Tag 来监控系统的每个组件。我们专门为某些组件建了 Slack 频道,让 Claude「痴迷地」盯一个组件的健康度。我们管这些 Claude 叫「superfan」。我们有 scion-daemon superfan、scion-cache superfan、Antique 合并队列 superfan 等等。它们能访问遥测和日志,活像一个经验丰富的工程师除了刷图表和盯异常外什么都不用做。我们对所有系统同时保留了传统的告警,但 superfan 能捕捉到那些让传统告警相形见绌的细微与新颖的问题。

这个项目促使我们重新审视其他按「人」的规模设计的流程。传统的合并队列在 agent 规模下基本没意义。当成百上千的改动在测试跑的同时已经合并,CI 本身意味着什么?我们没有能力有效复制合并队列的全局仓库锁,于是改为在合并后、部署前加大自动化测试投入。这意味着并发改动可能冲突,但 Claude 通常能比人识别冲突还更快地修复冲突。

我们把 Scion 视作「应对越来越强的 AI 代理带来的规模化挑战」这一答案的一部分。分享这些细节是希望对正在解决同类问题的团队有所启发——但我们不预期我们的方案或考虑普适到任何场景。

Scion 绝不是 git 在常规场景下的合适替代品。上文描述的设计只对真正巨型 monorepo、特别是有数万工程师或有大量 agent 持续产码的团队有意义。而且,Anthropic 在内部使用上能投入的 token 远超任何其他公司愿意投入的现实水平。我们做这件事既是出于自身研发需要,也是为了检验 Claude 的能力。

现实地说,要把 Scion 做成对其他组织广泛有用的形式并不容易。它与 git 严重分叉,意味着企业必须把整套研发生命周期都迁过来,还需要自配代码评审、代码搜索和 CI。我们这些内部组件都高度定制,其他组织很难直接采纳;而做一个试图取悦所有人的「公开版」又很可能谁都用不顺。

尽管如此,我们预期这类问题在接下来 6 到 12 个月内会变得普遍,再让每个用 git 的公司各自撞同一堵墙是研发资源的浪费。考虑到这一点,我们能做的最有影响力的事,就是把我们的思考分享出来,让其他开发者能把 Scion 中最成功的部分叠加到 git 上,而不必脱离 git 整体模型。git 服务器不必与 git 客户端的工作方式一致;新的服务器架构能带来显著的可扩展性改进。Git 平台也能像 Scion 那样提供完备的服务端 RPC,甚至可以在不同 forge 之间做标准化,让 git 客户端学会去对接。协商协议不必保持原貌,git 中各种 sparse/shallow 能力也可以更好地组合。

最后,我们想向 git 社区致敬——他们用了将近二十年为百万级开发者把平台规模化。我们的贡献很窄:把我们对 agentic 软件研发如何与这些系统互动的早期观察分享出来,让我们能跟 GitHub、GitLab 和开源社区一起支持开发者需求的变化。当软件研发生命周期与 AI 指数相遇时,我们都在同一条船上。

(文章为作者独立观点,不代表艾瑞网立场)
  • 合作伙伴

  • 官方微信
    官方微信

    新浪微博
    邮件订阅
    第一时间获取最新行业数据、研究成果、产业报告、活动峰会等信息。
     关于艾瑞| 业务体系| 加入艾瑞| 服务声明| 信息反馈| 联系我们| 合作伙伴| 友情链接

Copyright© 沪公网安备 31010402000581号沪ICP备15021772号-10

扫一扫,或长按识别二维码

关注艾瑞网官方微信公众号