本文永久链接 – https://tonybai.com/2026/08/25/cursor-continuity-git-walgit-spacex
大家好,我是Tony Bai。
【导读】
SpaceX 以 600 亿美元收购 Cursor 的消息还没冷却,Cursor 又在官网甩出一篇长达 27 分钟阅读时长的技术博客,详解自己憋了许久的「Origin」平台背后的 Git 存储引擎——Continuity。这篇博客把 GitHub 二十年踩过的坑、Spokes 系统的设计得失,以及一种全新的「WAL + 对象存储」思路讲得明明白白。更戏剧性的是:Shopify CEO Tobi Lütke 只用了一个周末,就把这套架构原封不动地用Rust实现了出来,开源发布,取名 walgit。这篇文章带你把这两件事一次看懂。
【文章要点】
- 背景:SpaceX 600 亿美元收购 Cursor 落地,几乎同时 Cursor 官网发布重磅技术博客《Git at any scale》;
- Git 托管为什么天生难扩展:packfile 设计、DAG 随机游走、GitHub 早期在 NFS / GFS / DRBD 上交的学费;
- GitHub 的答案 Spokes:三副本 + 三阶段提交(3PC),13 年的行业标准,也有扩展性天花板和运维成本两大硬伤;
- Cursor 的答案 Continuity:把对象存储(S3)里的写前日志(WAL)当作唯一真相源,本地磁盘只是「热缓存」,用 CAS 取代共识协议;
- 性能数据:S3 Standard 下 120 次推送/秒,S3 Express One Zone 下超过 300 次推送/秒,读吞吐随副本数线性扩展;
- 彩蛋:Shopify CEO Tobi Lütke 一个周末用 Rust 复刻出开源版 walgit,单文件二进制、支持任意 S3/GCS 对象存储、自带 bundle-uri 极速克隆;
- 延伸思考:AI Agent 时代对 Git 基础设施提出了全新的负载模型,这可能是继 GitHub、GitLab 之后,Git 托管架构的又一次范式转移。

600 亿美元收购之后,Cursor 没有庆功,先甩出一篇硬核博客
2026 年 8 月,AI 编程工具 Cursor 的开发商 Anysphere,正式并入刚刚完成史上最大规模 IPO 的 SpaceX,交易金额高达 600 亿美元、全股票支付。这笔收购把 Cursor 四位联合创始人的身价直接推上了十亿美元俱乐部,也让 SpaceX 一跃成为美股市值第四的公司。
但真正让技术圈炸锅的,不是这笔交易本身,而是收购官宣后不久,Cursor 在官网发布的一篇博客——《Git at any scale》(万物皆可扩展的 Git)。作者 Vicent Martí 曾是 GitHub 早期核心工程师,也是 libgit2 的创造者之一,这篇文章的分量,从作者履历上就能看出来。
文章的核心,是 Cursor 内部憋了很久的一个大动作:自研 Git 存储引擎 Continuity,并将其包装成一个即将对外提供的产品——Origin,目标很直接:成为 GitHub 的替代品,尤其是在「超大规模仓库」和「AI Agent 高频读写」这两个 GitHub 传统架构并不擅长的场景里。
这篇博客与其说是产品发布通稿,不如说是一篇系统架构论文。它把「为什么托管 Git 仓库这么难」、「GitHub 过去二十年怎么一步步踩坑」与「业界标准方案 Spokes 到底好在哪、又卡在哪」,讲得极其透彻,最后才给出 Continuity 的答案。
Git 天生就不是为「托管」设计的
Linus Torvalds 设计 Git 的初衷,只是为了取代 BitKeeper,服务于 Linux 内核这种高度去中心化、由无数独立维护者协作的项目。「分布式」是 Git 与生俱来的基因——每一份仓库的拷贝都是平等的、完整的,服务器上的仓库和你笔记本上的仓库,本质上没有任何区别。
这个设计哲学放在个人开发者身上没问题,但放到「一家公司需要集中托管成千上万个仓库,并让全球开发者和 CI 系统高并发读写」的场景里,就成了噩梦的开端。
问题的根源在于 Git 的存储格式:packfile(打包文件)。Git 仓库里的代码和元数据(文件、提交、树对象)都会被压缩进 packfile 里,这是 Git 存储和网络传输共用的基础单元——无论是 git push 还是 git fetch,传的都是 packfile。
packfile 的问题是:它是为了「体积最小」而设计的,对象在包里几乎是随机排列的,而且大多数对象并不是完整存储,而是相对另一个对象的「增量」(delta)。这意味着读取单个对象,往往需要在磁盘上做一次随机跳转式的「寻址接力」。

Git 的提交历史本质上是一张有向无环图(DAG)。哪怕是列出「最近的变更」这种简单操作,也必须沿着这张图一步步走下去——而且走到下一步之前,你根本不知道下一个指针指向哪里。
这也是为什么早期把 Git 对象直接扔进分布式哈希表(比如 Google 内部工程师 Shawn Pearce 基于 JGit 做的实验)最终没有成功——虽然常规操作没问题,但 git clone 的性能差到无法接受,因为 Git 协议本身要求网络传输的单位必须是 packfile,服务器内部存储方式再怎么创新,也逃不开这层限制。
GitHub 交的学费:NFS、GFS、DRBD,全部阵亡
GitHub 早期是一个跑在单台机器上的 Rails 单体应用,仓库就放在这台机器的本地磁盘上。Rails 应用本身很好水平扩展,但 Git 仓库要怎么「分身」到多台机器上,成了绕不开的难题。
GitHub 工程师们尝试过三条路:
- NFS:把所有仓库放在一台集中的文件服务器上,通过网络文件系统共享。Git 对本地文件系统的加锁、读写、同步行为做了大量假设,这些假设在网络文件系统上几乎全部失效——结果是又慢又不稳定。
- GFS(块级复制):短命阵亡。
- DRBD(块级复制):活得久一点,但同样「难以运维、性能不够」。
根本原因还是那句话:packfile 的物理布局和逻辑图结构毫无关联,这种「跨 GB 级数据的随机游走」在网络文件系统上是灾难性的——除非你能把整个文件缓存在本地,可当仓库数量达到数十万级别时,「全部缓存在本地」这个选项直接不存在。
最终 GitHub 放弃了「分布式文件系统」这条路,转而搭建了一套 RPC 系统,让仓库固定托管在专门的文件服务器上、应用层远程调用。这解决了一部分水平扩展问题,但没有解决可用性问题——每个仓库依然只存在于一台机器上。
行业标准 Spokes:好用了 13 年,但天花板越来越低
2013 年前后,GitHub 发展出了 Spokes 架构,这套思路后来成了整个行业的事实标准(包括 GitLab、Gitea 等在内的大多数 Git 托管方案,本质上都是 Spokes 的变体)。Spokes 做对了三件事:
- 不重新发明 Git,只在 packfile 这一层做文章;
- 所有数据依然以「正常 Git 仓库」的形式,存放在本地 NVMe 磁盘上;
- 多副本之间保持强一致,而不是最终一致。
第三点是关键。Git 客户端对「最终一致性」极不友好——如果你刚推送完一个提交,紧接着的 fetch 却读不到它,Git 会直接懵掉;如果 CI 流水线的一百个 runner 里有三个克隆不到刚推送的提交,同样是灾难。所以 Spokes 选择了一条很「重」的路:**用三阶段提交协议(3PC)**在多个副本之间做共识。

如上图所示:Spokes 用三阶段提交(3PC)在多个副本间达成共识。一次 git push 被拆成 packfile(大文件,直接并行分发到所有副本)和引用事务(reference transaction,体积小得多,用 3PC 同步),只有引用被更新之后,这次提交才算真正「可见」。
这套设计过去十几年确实稳,但 Cursor 博客点出了两个越来越致命的问题:
问题一:3PC 天生水平扩展性受限。
Spokes 刚发布时,「三副本」是甜蜜点——足够冗余,又不至于太贵。但到了 2026 年,企业级仓库普遍是巨型 monorepo,三个副本根本扛不住 CI 的并发读取压力。而 3PC 作为共识算法,每一步的延迟都取决于集群里最慢的那台机器——副本越多,推送吞吐反而越差,这是所谓「规模的尾部效应」(tail at scale)问题。
反过来也成立:当 AI Agent 开始大批量创建「用完即弃」的小仓库时,Spokes 依然要求每个仓库都维持三个副本,哪怕这个仓库几乎从未被访问——大量近乎闲置的副本,占着资源却裁不掉,因为裁掉就打破了一致性。下限太高,上限太低,Cursor 博客原话如此评价。
问题二:运维成本高到离谱。
因为每个副本上的仓库都是「共识的一部分」,你必须精确知道每个仓库存在于哪几台机器上——这意味着你需要一张巨大的路由表(外部数据库),仓库要不断校验和更新校验和,一旦发现损坏就要立刻修复,因为磁盘上的仓库本身就是「真相源」。用 Cursor 的比喻:Spokes 把仓库当「宠物」养,而不是「牲口」——每一份拷贝都金贵得不能出任何差错。
Continuity:把「真相」交给对象存储,本地磁盘只是缓存
看到这里,Continuity 的设计动机已经很清楚了:能不能既保留 Spokes「本地磁盘存真实 Git 仓库、复用上游 Git 工具链」的优点,又摆脱「共识协议 + 路由表 + 宠物式运维」这套沉重的包袱?
Cursor 给出的答案是:把写前日志(Write-Ahead Log,WAL)存进 S3 兼容的对象存储里,让它成为唯一真相源;本地磁盘上的仓库,退化成一份可以随时重建的「热缓存」。

我们看到:Continuity 的核心链路。一次 push 只有在 packfile 被完整写入 S3、且引用事务通过 CAS 成功更新索引文件之后,才会向客户端返回成功——这保证了所有推送都是可线性化的(linearizable)。
这套设计里,有几个反直觉但极其精妙的选择:
1. 仓库放在哪台机器上,不再重要。
Continuity 是无状态的,没有路由表,也没有关系型数据库需要运维。如果某台机器上没有你要访问的仓库,系统会直接从 WAL 里把它「物化」出来。生产环境里用的是 rendezvous hashing(会合哈希) 来决定「理论上」该由哪些节点服务哪个仓库,但这只是一种效率优化——就算这个映射过时了(比如某个节点挂了),系统照样能在下一个节点上重新物化出仓库,不会出任何数据问题。
2. 谁是「主节点」,同样不重要。
没有选举,没有共识协议。所有对 WAL 的更新都通过 S3 的原子比较并交换(CAS,Compare-And-Swap)操作来同步,这意味着任何一个副本都可以安全地接受一次推送。正常情况下系统会固定选择 rendezvous hashing 排序中的第一个节点作为「主节点」以减少 CAS 冲突重试,但即便在部署更新、故障转移、网络抖动这些边缘情况下选错了「主节点」,也完全没有关系——系统在退化时依然正确,在健康时依然快。

如图示:两个节点同时尝试推送时,CAS 天然扮演了「共识」的角色——谁先成功更新 etag,谁的推送就先生效;失败方只需重新拉取、rebase、重试。
3. 复制不再靠「强同步」,靠「随便传传,反正读的时候会自己校验」。
Continuity 用 UDP 广播(gossip)把「有新数据了」这件事随意地告诉集群里的其他节点——丢包完全没关系。因为每个副本在处理一次读请求时,都会先拿着自己记录的 etag,向 S3 发一次条件 GET(conditional GET):返回 304 说明数据没变,几乎是零延迟的元数据操作(平均不到 10 毫秒);返回 200 则带着最新的索引,副本用它「追平」进度后再响应请求。换句话说,副本之间的数据到底同没同步,根本不重要,因为每次读都会向 S3 这个真相源核对一遍。
这种设计带来了一个非常直接的好处:副本数量可以在两个方向上自由伸缩。一个巨型 monorepo 可以铺开成百上千个副本来扛住 CI 的读取洪峰;而 AI Agent 批量创建的海量小仓库,一个副本就够,因为可用性已经由 S3 兜底了;如果某个仓库长时间没有流量,甚至可以把它从本地磁盘上彻底垃圾回收掉,下次访问再从 WAL 重新物化。
4. 压缩(compaction)只做一次,其他副本「白嫖」结果。
WAL 系统都需要定期压缩,Git 仓库本身也需要定期 repack(否则大量小 packfile 会拖慢对象查找)。在 Spokes 里,repack 是个 CPU 密集型操作,且必须在每个副本上各自执行一遍——两个节点同时对同一仓库触发维护操作,很容易直接把仓库拖挂。Continuity 的做法是:只有「主节点」做压缩,压缩结果同时写回本地仓库和 WAL,其余副本只需要从 S3 下载已经压缩好的 pack,用带宽换 CPU,不用各自重复计算。
性能数据:读吞吐随副本数线性扩展
Cursor 在博客里给出了压测数据:
- 在多达 100 个副本的合成压力测试中,读吞吐随副本数量线性增长,推送吞吐没有出现任何退化;
- 使用标准 S3(S3 Standard),集群可以稳定支撑 每秒 120 次推送;
- 使用延迟更低的 S3 Express One Zone,推送吞吐可以突破 每秒 300 次,此时瓶颈已经不再是 S3,而是 Git 在本地做压缩的速度。

值得一提的是,Continuity 并不是「第一个把 packfile 存进对象存储」的系统——微软的 Azure DevOps 早就在用 blob 存储存 packfile,但引用(ref)数据仍然放在关系型数据库(MS SQL Server)里。Cursor 的判断是:Git 数据的一致性,比引入一个额外的数据库带来的便利更重要,这也是他们最终选择「完全基于 WAL、不依赖任何外部数据库」这条更难走的路的原因。
彩蛋:Shopify CEO 一个周末,把它开源复刻了出来
如果故事到这里结束,这只是一篇优秀的架构博客。真正让这件事出圈的,是 Shopify CEO Tobi Lütke 在 X(原 Twitter)上的一条推文:
「Cursor 那篇《Git at Scale》是我近期读过最有意思的博客之一,而且它出现的时机正好是我对 Shopify 内部 Git 系统感到沮丧的时候。作为一个练习,我用一个周末把它实现成了开源项目。这是一个单文件 Rust 二进制程序,可以指向任意 S3 类型的对象存储。它使用 WAL 和 CAS 原语,不需要任何其他数据存储。它还实现了 bundle-uri,让像我们的 monorepo 这样的大仓库能作为一串静态 bundle 文件被极速下载。还带了基本的、大家熟悉的操作界面。」
这个项目叫 walgit,托管在 github.com/tobi/walgit,短短时间内已经收获上百个 Star。它的 README 开门见山:
walgit —— 一个「单文件二进制 + 对象存储」的 Git 服务器,没有数据库,没有主节点,没有任何真正重要的本地状态。
walgit 本质上就是 Continuity 架构的一份忠实(且工程上更进一步)的 Rust 复刻实现,README 里甚至直接写明:「这是对 Cursor 在《Git at any scale》中描述的架构(他们称之为 Continuity)的 Rust 实现,并做了一些改动,让它能在比仓库本身还小的机器上运行。」 原文甚至被逐字保存在了仓库的 docs/reference/cursor-git-at-any-scale.md 里。
walgit 的几个亮点
- 真的只有一个二进制文件:写一份配置指向任意 S3 或 GCS 兼容的存储桶,运行
walgit serve,第一次git push就会自动创建仓库——没有任何额外的初始化步骤。 - bundle-uri:让巨型仓库的「首次克隆」快到飞起。walgit 会按日历节奏(每周一个全量 bundle,每天叠加增量,可选每小时级别)切割仓库快照,全部是静态文件,可以直接扔进 CDN 分发。一次全新的
clone只需要下载「最新的全量 bundle + 之上的增量链」,服务器只需要补齐剩下的一点点差异;一次日常的fetch也只需要下载自己错过的那几个增量片段。 - 面向「仓库比机器还大」的场景做了专门优化:walgit 引入了「远程读取器」(通过 HTTP Range 请求按需读取 S3 里的对象)、「历史 pack」(commit 和 tree 留在本地,体积更大的 blob 留在对象存储里)等机制,专门解决「monorepo 装不进一台小机器」的问题——这是比 Cursor 原始设计更进一步的地方。
- 麻雀虽小,五脏俱全:内置 Git LFS、一个 React 写的 Web UI(浏览代码树、Diff、提交历史)、一个依赖极少的 JSON API + SDK(
repos.js)、基于 Webhook 的事件推送、per-repo 的推送策略(保护分支等)、以及none / token / oidc三种鉴权模式。

如图,walgit 的整体架构——每台机器都是「可丢弃的缓存」,对象存储桶才是真正的仓库;bundle-uri 让「首次克隆」这种最消耗服务器资源的操作,直接绕过服务器,走静态文件分发。*
这条推文下面,Tobi Lütke 特别 @ 了 Cursor 博客作者 Vicent Martí(其 X 账号为 @vmg),感谢他这篇「amazing writeup」。一篇架构博客,从发布到被行业里另一位知名 CEO 用一个周末逆向实现并开源,中间几乎没有信息损耗——这本身也是这个 AI 编程时代的一个缩影:当写代码的边际成本被 AI 大幅拉低之后,「读懂一篇硬核架构文章,然后把它变成可运行的系统」这件事,正在变得越来越快。
为什么这件事值得关注
抛开「大厂互撕」、「CEO 周末搓开源项目」这些吃瓜元素,这件事背后有几层更值得琢磨的信号:
第一,AI Agent 正在从根本上改变 Git 基础设施的负载模型。
过去 Git 托管系统的假设是「人类开发者,有限并发」;而现在,一个团队里可能同时跑着成百上千个 AI Agent,各自创建、废弃、重写着海量的小仓库和分支,CI 触发频率也水涨船高。Cursor 博客里那句「Spokes 对付海量小仓库时,下限太高、上限太低」,说的正是这个新负载模型下暴露出的旧架构短板。
第二,「无状态 + 对象存储做真相源」正在成为一种新的系统设计范式。
从数据库(Neon、别的 serverless Postgres)到现在的 Git 托管,越来越多的基础设施选择把「本地磁盘」降级为缓存,把「对象存储」提升为真相源——这背后的驱动力,是云对象存储在可用性、持久性和成本上的持续进化,让「什么都往 S3 里怼」从一个笑话变成了一种严肃的架构选择。
第三,开源社区对「巨头架构」的复现速度,正在急剧压缩。
一篇博客发布不到几天,一个足够熟悉系统设计的资深工程师就能用 Rust 独立复刻出一个可用的开源实现,这在几年前是难以想象的效率。对于任何还想靠「架构护城河」构筑壁垒的公司来说,这是一个值得警惕的信号。
第四,也是最直接的:Git 托管这个被 GitHub 垄断了近二十年的市场,可能正在迎来一次新的洗牌。
Cursor 把 Continuity 包装成产品 Origin 对外提供,摆明了要正面挑战 GitHub;而 walgit 这样的开源实现,则给了那些不想被单一厂商绑定、又对自建 GitLab / Gitea 集群的运维成本感到头疼的团队,多了一个「单文件 + 对象存储」的轻量选项。
小结
一篇博客,两套系统,一场围观。SpaceX 收购 Cursor 的商业新闻很快会被下一条新闻覆盖,但 Continuity 这套「用对象存储里的写前日志取代共识协议和关系型数据库」的设计思路,以及 walgit 这个周末产物证明的「架构一旦讲透,落地可以有多快」,或许才是这几天真正值得被记住的东西。
如果你的团队也正被 Git 仓库的扩展性问题折磨——不管是巨型 monorepo 拖垮 CI,还是 AI Agent 批量创建仓库把自建 GitLab 集群压垮——这篇 Cursor 博客原文,以及 walgit 这个开源项目,都值得花时间读一读、跑一跑。
参考链接
- Cursor 官方博客《Git at any scale》:https://cursor.com/blog/git-at-any-scale
- walgit 开源仓库:https://github.com/tobi/walgit
- Tobi Lütke 相关推文:https://x.com/tobi/status/2091678506992222258
- SpaceX 收购 Cursor 相关报道(TechCrunch):https://techcrunch.com/2026/06/16/spacex-to-acquire-cursor-for-60b-in-stock-days-after-blockbuster-ipo/
还在为写 Agent 框架频频死循环、上下文爆炸而束手无策?我的新专栏 《从0 开始构建 Agent Harness》 将带你:
- 抛弃臃肿框架,回归“驾驭工程 (Harness Engineering)”的第一性原理
- 用 Go 语言手写 ReAct 循环、并发拦截与上下文压缩引擎等,复刻极简OpenClaw
- 构建坚不可摧的 Safety Middleware 与飞书人工审批防线
- 在底层实现 Token 成本审计、链路追踪与自动化跑分评估
- 从“调包侠”进化为掌控大模型边界的“AI 操作系统架构师”
扫描下方二维码,开启从 0 开始构建Agent Harness 的实战之旅。

还在为“复制粘贴喂AI”而烦恼?我的新专栏 《AI原生开发工作流实战》 将带你:
- 告别低效,重塑开发范式
- 驾驭AI Agent(Claude Code),实现工作流自动化
- 从“AI使用者”进化为规范驱动开发的“工作流指挥家”
扫描下方二维码,开启你的AI原生开发之旅。

商务合作方式:撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。如有需求,请扫描下方公众号二维码,与我私信联系。
