Git遇上大模型(1): OpenAI 如何扩展 Git
原文:Scaling Git at OpenAI
作者:Aaron Friel、Taylor Blau、Ted Nyman
原文发布日期:2026 年 11 月 2 日
本文为中文翻译,技术术语和代码标识尽量保留原文写法。
过去一年,我们的单体仓库在规模和负载需求上增长惊人。Codex 让大量工作得以并行展开,我们显然需要改造源码控制系统,才能支撑这种并发程度。
我们构建了 Pando:一个新的 Git 仓库后端。在此过程中,工程工作没有中断,团队使用 Git 的方式也没有改变。现在,Pando 支撑着 OpenAI 单体仓库中的全部开发工作。它要实现两个目标:一是支持横向扩展的写入,尤其针对大量分支的并发推送;二是尽可能提高读取吞吐量,让客户端能够以接近自身网络带宽上限的速度下载数据。
我们实现了这些目标,同时保持了与 Git 协议和客户端的兼容,让工程师和智能体都能沿用现有工作流。在生产环境中,Pando 使推送延迟的中位数降低了近五倍,目前每天传输的 Git 数据量接近 1 PB。
本文将介绍构建新源码控制系统的动机,以及我们为何坚持兼容 Git;也会将 Pando 与常见的 Git 扩展方案比较,说明它为何能满足 OpenAI 的规模需求,并谈谈后续计划和我们将如何继续为 Git 贡献改进,以支持智能体规模的工作负载。
为什么需要新的源码控制系统
Codex 改变了 OpenAI 的开发规模和节奏,让工程师能够同时推进更多工作。这意味着更多分支和推送、更多合并,以及来自开发环境、研究任务和 CI 的更多拉取与克隆。
这些需求会相互叠加。现在,一名工程师可能同时有几项改动等待 CI,而每次推送又可能触发多个任务去拉取同一个提交。
从去年年底左右开始,支撑单体仓库的系统逐渐跟不上需求。拉取和推送变慢,合并失败,可靠性有时降到 90% 以下。我们遇到的究竟是 Git 本身的极限,还是当前仓库服务方式的极限?Git 诞生于通过电子邮件交换内核补丁的社区。二十多年来,随着软件开发方式演变,开发者不断调整围绕 Git 的工具。我们自己的单体仓库开始出现阻力时,继续利用这些积累对我们很重要。
我们发现,可以保留熟悉的工作流,同时重建后端:让不同分支的推送并行处理,并把同一份历史同时提供给大量读者。继续以 Git 作为源码控制工作流的基础,也意味着客户端的改进能惠及 OpenAI 之外的用户。我们希望把 OpenAI 的 Git 分支中的改进贡献回上游,与整个社区分享。
面向规模化 Git 的工程设计
扩展源码控制系统有两个关键维度:许多写入者向不同分支推送,以及许多读取者获取同一份历史。Pando 同时针对这两方面优化。
首先,Pando 独立协调每个分支的更新。互不相关的分支可以并行更新;读取某个分支的客户端则会获得该版本所需的历史。代价是,读取多个分支的客户端可能看到它们处于不同的时间点。
其次,Pando 在不同拉取请求之间复用 packfile(Git 用来将多个对象压缩在一起的格式),而不是为每个客户端单独生成 packfile。客户端可能下载到自己已有的部分对象,但服务器能以很少的计算量向众多客户端发送同样的数据。
这些选择让我们能够跨分支扩展写入,并从缓存提供读取。要理解它们如何配合,先看看 Git 如何存储和传输历史。
Git 对象存储简介
Git 必须让仓库中的两部分保持同步:对象和引用。
Git 仓库用对象图记录文件快照及连接这些快照的历史。对象可以是 blob、tree、commit 或 tag。blob 保存单个文件的内容;tree 将名称与 blob 或其他 tree 关联,组成目录结构;commit 指向根 tree 和零个或多个父 commit,构成仓库历史。
对象以其类型和内容的哈希值标识,而且不可变。记录一个修改过的文件会创建新的 blob;未修改的文件和目录则可以继续复用已有对象。
分支和标签是指向 commit 的引用(ref)。在某个分支上提交时,会创建新的 commit,并更新该分支的 ref,使其指向新提交。
Git 对象之间通过 ID 互相引用:commit 指向 tree,tree 再指向其他 tree 和 blob。分支 refs/heads/main 指向提交 C2,C2 的父提交为 C1。C1 指向根 tree T1,其中 parser.py 对应 blob B1。C2 指向根 tree T2,其中 parser.py 对应 blob B2。两个根 tree 中的 docs/ 都指向同一个 tree T3;T3 中的 README.md 和 usage.md 分别指向 blob B3 和 B4。
Git 对象可以是“松散”或“打包”状态。松散对象按对象 ID 分别存储在单独的文件中;打包对象则共同存放在 packfile 中,从而可以把相似对象编码为彼此之间的增量。
Git 可以把 blob 分别存成文件,也可以把它们打包,将其中一个 blob 编码为相对于另一个 blob 的增量。
如果 Git 从某个 commit 出发,沿着父提交、tree 和 blob 的引用能够找到一个对象,就称该对象从这个 commit 可达。拉取时,客户端告诉服务器自己想要哪些 commit、已经拥有哪些 commit。服务器找出从目标 commit 可达的对象,排除它确认客户端已拥有的对象,再把剩余对象作为 packfile 发送,格式与 Git 磁盘上的 packfile 相同。完整克隆的客户端一开始没有任何对象,因此需要取得从所克隆历史可达的全部对象。
推送则反向传输对象,并请求服务器更新一个或多个 ref。客户端利用服务器公布的 ref 集合,避免发送服务器已经拥有的对象。因此,发送的 pack 可能依赖服务器已有的对象:仅仅收到 pack,并不足以重建新历史。
复制一个 Git 仓库,需要让对象和引用都能在多台服务器上使用。副本在提供某个引用的新值之前,必须能提供从该值可达的对象。服务还需要协调相互竞争的引用更新,例如两个推送都想把同一分支从相同的旧端点移动到不同的新提交。如果系统要求仓库内的全部写入遵循同一顺序,那么推送到无关分支的操作也可能互相等待。
现有的分布式 Git 服务模式
在设计 Pando 时,我们评估了两种常见的 Git 源码控制扩展方案:一种通过三阶段提交(3PC,一种协调多个节点提交的协议)来协调仓库副本间的 ref 更新;另一种通过 blob 存储中共享的预写日志(WAL,在应用改动前先记录改动)为更新排序。
三阶段提交(3PC)
在我们建模的三阶段提交设计中,Git 服务在多个副本上各保留一份完整仓库。任一服务器收到推送后,会复制收到的 packfile,并行发送给所有副本。发布该推送时,必须有多数副本接受 ref 更新。管理这一过程的服务器称为协调者,它需要与其他各副本进行多轮通信。
要接受引用更新,每个副本都要锁定本地的 ref,并检查它是否仍指向客户端预期的 commit。随后,协调者向接受更新的副本发送预提交消息;得到多数副本的确认后,再指示它们执行更新。此后,任何已更新的副本都可以从本地仓库向客户端公布新的分支端点。
保留完整副本使服务器能够在本地处理读取,也保证客户端无论选择哪个副本,都能看到全部引用的一致视图。相应地,引用只能逐一更新,每次推送都需要在副本之间往返通信多次。
等待法定多数达成一致,会把副本磁盘性能和通信延迟放到推送的关键路径上。写入量增长时,副本必须同时跟上新增 pack 和读取流量。
预写日志(WAL)
在我们建模的 WAL 方案中,Git 服务使用 blob 存储里的共享清单,对整个仓库的更新排序。服务器收到推送后,将传入的 packfile 上传到 blob 存储,并在本地仓库准备 ref 更新。要发布推送,它会向共享清单追加一个条目,记录 ref 更新及对应的 packfile,然后使用比较并交换操作更新清单。成功时,清单会被原子替换;失败则说明发生竞争。如果其他写入者已更新清单,服务器会读取期间新增的条目,检查自己的 ref 更新是否仍然有效,然后复用已经上传的 packfile 重试。
写入者可以并行上传 packfile,但即使推送到互不相关的分支,也必须更新同一份清单。一次成功的比较并交换操作的往返时间,限制了仓库发布新清单的频率。低延迟的 blob 存储可以加快这一步。批处理可在一次清单更新中处理多个 ref,但代价是排队和更高的延迟。
blob 存储可以并行接收 packfile,但共享清单的更新仍会互相争用。单纯增加 blob 存储容量无法消除这一瓶颈。每个副本在从本地提供 pack 前,还必须从 blob 存储读取并建立索引。如果新增写入超过处理速度,副本就会落后,客户端拉取新提交时也要等待更久。
Pando 的架构
这就引出了 Pando。它是一种新的 Git 仓库服务架构,目标是支持大量客户端同时推送。下面介绍其工作方式。
重新审视约束
开发 Pando 之前,我们认为不放弃 Git 也能满足需求,但必须放弃一些多数 Git 系统视为必需的假设:
- 仓库范围内的一致性:若要为所有 ref 提供同一时点的一致快照,就必须在整个仓库范围协调。在统一排序所有 ref 更新的系统中,无关分支的推送也会争用同一个协调点。
- 为每个客户端生成独有的 packfile:两个本地历史不同的客户端拉取同一分支时,服务器可能需要分别生成 pack,避免发送它们已有的对象。生成这些响应消耗 CPU 和磁盘 I/O,难以扩展到大量读取者。
Pando 则采用较宽松的一致性模型(因果一致性)来扩展写入,并通过复用 packfile 扩展读取。
因果一致性(CC)
客户端向某个分支推送时,Pando 会把传入的 packfile 作为不可变 blob 存入 blob 存储。分支每移动一次,Pando 就在元数据存储中记录一个 ref 版本,包含新的端点、提供该端点的 pack,以及该 pack 所依赖的更早 ref 版本。blob 存储和元数据存储都可以横向扩展。
从 Pando 拉取 commit 或引用时,需要向客户端重放一组 ref 版本(packfile),重建产生目标 ref 版本的客户端当时的状态。这使仓库整体采用较弱的一致性,而单个 ref 的更新仍可串行化。只有同时向同一个 ref 推送的客户端才会冲突。读取多个分支的客户端,不能假定这些读取结果代表仓库在同一时刻的状态。
一次向主干推送会新增一个包含一个或多个提交的增量 pack。每次向旁支推送也会再次包含该主题分支较早的提交,因此拥有服务器公布的主干版本的客户端,可以用一个 pack 拉取该旁支。
这是一种因果一致性:读取某个引用时,读者能看到产生这个版本的写入者所见过的历史。推送过程中,Pando 控制客户端与服务器就哪些共同历史达成一致,让客户端生成更容易共享的 packfile。
因此,Pando 不会在 Git 操作期间提供全部引用的同一时点状态,也不会为一次克隆或拉取中的 ref 更新给出统一顺序。例如,在完整克隆的协商期间,foo 和 bar 两个分支都发生更新:一个客户端可能看到版本 1 的 foo 和版本 2 的 bar,另一个客户端则可能看到版本 2 的 foo 和版本 1 的 bar。实际使用中,用户和智能体并不依赖 ref 更新的全局顺序,而是依赖单个 ref 内部的更新顺序。
比较不同方案
在三种一致性模型的模拟中,我们配置 1,000 个客户端,让每个客户端选择一个不同的分支,并反复推送各自独有的提交,测量总耗时和从推送到可拉取的延迟。后一项对实际工作负载很重要,因为它衡量用户、智能体以及依赖版本控制的其他系统协作时的往返时间。模拟涵盖从普通到高端的虚拟机及 blob 存储系统。在这个模拟中,我们放宽了三阶段提交方案的仓库范围一致性要求。
模拟 Git 服务器实现
跟踪每个写入者的连续推送,并分别测量独立的读取者何时能检出每次提交。
原文提供了一项交互式模拟,可比较 Pando 与另外两种方案,并调整硬件档次、客户端数量等设置。模型显示,磁盘在负载下饱和时,三阶段提交系统的写入延迟明显更高;预写日志系统则因为服务器难以及时读取日志,同等条件下读取延迟明显更高。无论是在我们单体仓库的真实测试中,还是在这项模拟中,Pando 都能支持数千个客户端并发推送,而负载增加不会损害性能。
处理推送时,Pando 在将传入 packfile 流式写入 blob 存储的同时进行验证,无须将它解包到本地仓库。客户端开始拉取时,Pando 选择读取者所需的已存 pack,再由读取者下载。没有服务器需要把 packfile 应用到本地仓库,也无须执行昂贵的解包和重新打包。由于服务器主要负责协商与 packfile 选择,Pando 服务器可以运行在普通硬件上。
这样,Pando 的扩展上限主要取决于客户端、客户端与 Pando 之间的网络,以及 blob 存储服务。在容量充足时,各客户端即使在不同分支上工作,也能以各自连接允许的速度传输 pack。要按同样速度服务更多客户端,我们可以增加 Pando 服务器,并相应扩展元数据和 blob 存储。
在 Pando 中推送和拉取分支
Pando 把写入者的 packfile 存入 blob 存储,在元数据服务中记录 ref 版本。拉取时,Pando 选择读取者需要的 pack,并由 Express 提供下载。
智能体在本地编辑文件、创建提交,再运行 git push。Git 由这些改动生成 packfile,用来更新分支。Pando 接收 pack,并将其流式写入 blob 存储。通过单次解码验证传入的推送后,Pando 用一个多键事务在元数据存储中记录 ref 版本,并原子更新 ref 指针。这使 Pando 能提供“读到自己刚写入的数据”的一致性。整个写入操作只需要 O(1)O(1) 次元数据读写。
另一个客户端拉取该分支时,Pando 会根据客户端已有的历史选择一组已存 pack。该操作需要 O(logΔ)O(\log \Delta) 次元数据读取,其中 Δ\Delta 是客户端已有版本与目标版本之间最短的 ref 版本距离。服务器返回 packfile URI,客户端通过 Express 下载 pack;Express 会在各区域缓存 packfile。
这一设计依靠 Pando 架构中的三个核心环节:推送、拉取和压实。
扩展推送能力
客户端推送时,传统 Git 服务器就像摊开全部手牌的扑克玩家:它会向客户端公布自己拥有的每一个分支。客户端随后收集 commit、tree 和 blob,生成一个排除了已知服务器拥有对象的 packfile。
公布更多 ref 可以让推送更小,但也可能使 pack 更难复用,因为其他客户端未必拥有写入者从 pack 中省略的对象。
Pando 采用另一种方式:它不会亮出全部手牌,只向客户端公布选定的一组分支。原因有两个:
- 提供每个 ref 的一致视图代价很高。当分支数达到数百万时,仅 ref 公告就可能超过 100 MiB。为此,每台服务器要么维护最新的映射,承担大量协调开销;要么进行开销随 ref 数增长的数据库查询。
- 只向客户端提供部分 ref,可让客户端生成一个只依赖服务器明确允许它省略的对象的 pack。Pando 跟踪这些依赖后,就能把一次推送生成的 packfile 复用为后续拉取的响应。
Git 服务器公布的 ref 越多,推送客户端可据以排除对象的来源也越多,生成的 pack 往往越小。但要复用这些 packfile,服务器就必须证明每个拉取客户端都拥有其全部依赖,否则 packfile 可能缺少客户端所需的对象。
反过来,如果 Git 服务器一个 ref 都不公布,客户端就会生成包含仓库全部历史的 packfile。这样的 pack 可供任何客户端使用,代价却是拉取任意分支几乎都变成一次完整克隆。
公布更多 ref 会得到更小的 packfile,但只公布一个 ref,就可能带来大部分体积收益。
默认情况下,客户端推送新的特性分支时,Pando 只公布指定的主干分支作为基线。这样,分支数增加也不会扩大 ref 公告,但存在取舍:工程师反复向同一分支推送,或把一个特性分支叠在另一个之上时,客户端必须重新发送主干之外的全部内容。
这会让后续分支推送变大,包含可能重复的对象,并消耗更多客户端带宽。在我们的单体仓库中,以这种方式生成的 packfile 中位数小于 20 KiB,99 分位数小于 3 MiB。我们认为这是合理的取舍,因为已经拥有所公布主干历史的读者,只需这一个 packfile 就能拉取分支。
选定向客户端公布的 ref 集合后,Pando 接受推送并更新元数据存储。它把元数据更新分成同步和异步两部分。同步更新保证客户端能够立即拉取新提交:写入新的 ref 版本,并更新指向该版本的 ref 指针映射,保存新端点、协商 packfile 时使用的依赖,以及所推送 packfile 的链接。
与此同时,安排压实等异步工作也会记录在同一个事务中。对于非常大的推送,同步写入的只是部分 commit。这让我们不论推送规模如何,都只需对元数据存储执行常数次读写。
关键在于,Pando 服务器可以独立接收发往无关 ref 的推送。唯一发生争用的键是 ref 指针,我们用类似原子比较并交换的操作保护它。增加 Pando 服务器、元数据存储的扩展单元或 blob 存储,就能提高写入吞吐量。
线速拉取与克隆
客户端发起拉取时,会向服务器提供两组 commit ID,在协议中称为 have 和 want。传统 Git 服务器计算从 want 可达而从 have 不可达的对象集合,将其压缩后发送。开源 Git 服务器虽然使用多种本地索引来加速这一步,但生成 packfile 仍可能代价高昂,也通常难以缓存。
Pando 则利用推送时记录的 commit 映射查找客户端的 have 和 want,将它们解析成包含相关 commit 的 ref 版本。每个 ref 版本都链接到 Pando 先前收到的 packfile。服务器据此计算客户端需要哪些对象,并选择覆盖这些对象的 packfile。
在 Pando 中规划拉取
Pando 比较客户端已有和想要的数据,选择所需的已存 packfile,其中也包括缺失的分支依赖。
原文交互图示以“已拥有”“需要拉取”“缺失的分支依赖”等状态展示这一过程:例如拉取 27 个主干 pack,或者选择一个分支并补齐它在主干上的依赖。Pando 把 Git 协议中的 have 和 want 映射为一系列 ref 版本;请求旁支也意味着请求它所依赖的主干版本。
Git 协议只允许在克隆或拉取的 HTTP 响应中发送一个 packfile。但协议中一个常被忽视的功能 packfile-uri,允许服务器返回额外 pack 的下载链接。Pando 完全依赖这一功能,直接在响应中发送一个空 packfile。为了支持它,OpenAI 向上游贡献了多项 packfile-uri 改进。
OpenAI 的系统运行于多个地理区域,因此我们在每个区域维护带有本地缓存的 Pando 集群。一个名为 Express 的 pack 交付服务缓存 blob 存储,另一个服务缓存元数据存储。有了这些缓存,Pando 可完全基于集群中的缓存状态,处理针对 commit ID 的请求或对 ref 的特殊读取。我们使用一致性哈希把 packfile 请求路由至 Express 服务器,缓存命中率超过 99%。
这一缓存体系具有极高吞吐量,足以跑满客户端与 Pando 之间的网络带宽。借助 packfile URI 和本地缓存,我们已验证:仅使用云服务商的标准虚拟机,克隆和拉取就可以跑满 10 Gbps 网络链路。
压实与首字节时间
多数 Git 服务器都需要重新打包和垃圾回收,才能维持不断增长的仓库性能。这两个步骤都能回收空间,却很耗费计算和 I/O。
在 OpenAI 单体仓库这样变化迅速的仓库中,不可能为客户端上次拉取以来的每次推送分别发送一个 packfile URI。若要追上主干,客户端每天可能需要下载数万个 packfile。
因此,Pando 在后台合并 pack,以减少这部分开销,其设计类似日志结构合并树(LSM tree)的压实。每次推送都会生成一个 Pando 所称的“L0” packfile,它代表 Pando 可传输的最小数据单位。随着时间推移,后台工作进程把这些 packfile 收集成覆盖一系列 ref 版本的集合(cover),从 L0 开始按几何级数扩展。目前,我们的单体仓库使用最高到 L4 的 packfile cover。
这些 cover 有双重用途。一个 cover 足够满后,压实进程会领取它并生成单个 packfile,通过重新组织其中的对象提高压缩率。与此同时,cover 还相当于覆盖 ref 版本的跳表,可提高拉取协商性能。Pando 同时扫描各级索引,便能以对数时间选择要发送给客户端的 pack 集合。无论 cover 中的 pack 是否已重新打包,它们都能提高拉取规划效率,降低 Pando 对吞吐量和延迟的要求。
Pando 中的压实
原文图示展示了小 packfile 如何跨 L0、L1、L2 等层级合并成更大的 cover,以提高压缩率并加快拉取。后台压实将许多 ref 版本的 packfile 合并,使客户端可以用更少文件完成拉取。
与许多 Git 服务器不同,各级 packfile 都会保留,不会被丢弃或进行垃圾回收。根据拉取请求中的 have 和 want,Pando 会持续使用各层的 pack 向客户端提供数据。对于把 Pando 作为 API 使用的客户端,从 packfile 读取任意对象时,读取 L0 所需的数据通常少于 L4,因为 L0 中该对象被压缩的可能性更低。
Pando 的压实显著减少发送给客户端的总数据量,也让 pack 规划的成本随客户端落后程度呈次线性增长。对于规模大且变化快的仓库,这一点尤其重要;我们预计这种仓库会成为软件开发的新常态。
构建 Pando
我们借助 Codex 构建 Pando,从启动项目到投入生产只用了 10 周。Pando 的核心由一名工程师设计,由多个智能体团队实现,并由少数工程师部署。今年 4 月,Pando 开始承载生产流量;它是 OpenAI 更大范围源码管理工具体系的一部分。
验证 Pando 设计时,我们采用了多种方法,并遵循构建更安全的软件基础的原则。作为一个从零开始的项目,我们选择用 Rust 实现 Pando,不引入历史遗留依赖。我们编写了符合性测试套件,让智能体可以对照标准 Git 行为检查改动;还开发了确定性的模拟测试框架,用来验证系统不变量和性质,发现并缓解协商及 pack 规划中隐蔽的竞争条件和回归问题。
许多模型参与了这个系统的建设。随着新模型出现,我们继续用它们改进 Pando 的性能和可靠性。借助 GPT‑6 Astra,智能体用 Lean 和 TLA+ 形式化了一套“Pando 理论”,帮助我们发现并修复实现中的错误,证明系统性质。多个连续运行数百小时的会话负责查找和修复边界情况。我们还全天候运行智能体,使用具备 Daybreak 能力的模型对 Git 和 Pando 进行红队测试。
部署 Pando
Pando 最初作为现有源码控制系统的读写直通代理部署。这使 Pando 与旧系统保持同步,从而可以在不停机的情况下,安全地将流量逐步迁移到 Pando。
得益于缓存设计,Pando 还能在代理转发前对请求去重和合并。因此,我们逐一迁移系统时,现有工具仍能正常运行。随着更多工作负载迁入 Pando,它们的推送也逐步填充 Pando 的缓存,并提高了旧后端的可靠性。
为了优化 Pando 的使用性能,我们开始向开发机以及 ChatGPT 桌面应用分发公开版本的 Git。客户端迁移则通过内部 Git CLI 封装工具分阶段进行。与此同时,我们还构建了许多处理变更请求、代码审查和自动化 API 的工具;除了 Git 流量,也迁移了数百个依赖旧 API、webhook 和仓库下载的集成。
Codex 本身也帮助开发者和团队完成迁移。我们编写了用于准备现有检出目录、指导智能体使用新系统的技能。因此,开发者只需让 Codex 迁移自己的开发环境和服务即可。
切换到 Pando 后,合并可靠性提高,推送延迟的中位数降低了近 80%。
Pando 只需少量 CPU 核心,就能每天传输 1 PB 的 Git 数据。它曾在一小时内提供超过 57 TB 的 Git pack,其中超过 99% 的字节来自本地磁盘缓存。
复用 pack 让许多客户端下载同一份仓库历史时,服务节点只需执行很少的计算。这个例子展示的是单个仓库,但 Pando 的设计能够支持更多仓库。随着需求增长,我们可以独立扩展数据交付和 Git 协商能力。
回馈 Git 项目
以 Git 协议和客户端为基础构建 Pando,也帮助我们发现 Git 自身的错误和性能改进机会。
例如,Pando 直接向客户端提供可复用的 pack,因此下载并索引这些 pack 成了保证系统快速、可靠的关键环节。这项工作暴露了并发下载、传输中断后的清理,以及已完成下载的恢复等边界情况。我们修复了相关流程,在拉取时接受已有 pack 的环节增加验证,并将这些改动贡献给上游。
我们还需要弄清楚时间和带宽消耗在哪里,因此为 packfile-uri 下载增加了追踪信息,并统计生成 pack 时的字节数。这样更容易判断拉取慢是耗在生成 pack,还是耗在传输上。
在 OpenAI 的 Git 版本中,客户端可以并行下载和索引互相独立的 pack。我们还引入“显式 have”的概念,让服务器分别公布分支当前端点,以及推送客户端在生成 pack 时可以省略的历史。在 Pando 上,这使客户端能够使用 --force-with-lease 检查特性分支是否被别人移动,并只以主干为基础生成 pack。任何拥有该主干历史的客户端,随后都能使用同一个 pack 拉取该分支。
其中一些改进已经进入上游 Git,还有许多改进收录在我们的公开仓库中。我们将继续与 Git 社区合作,让这些改进在 Pando 之外也能发挥作用。进展可见于我们的公开补丁追踪器。
下一步
通过重新审视扩展 Git 仓库的传统假设,Pando 使我们能够扩展单体仓库,而工程师与智能体不必改变已有的 Git 工作流。在我们的单体仓库里,Pando 提高了并行程度和合并可靠性,也缩短了发布代码改动所需的时间。我们还在探索 OpenAI 内部的其他用途,包括需要大量智能体在同一个 Git 仓库中协作的工作负载。
随着工程师和智能体创造出更多软件,OpenAI 之外的团队也会遇到我们碰到的源码控制系统瓶颈。我们目前正在探索如何与用户分享支撑 Pando 的技术。
Pando 建立在 Git 仓库用户和运营者二十多年的经验之上。我们会继续开发 Pando,同时与开源 Git 社区合作,分享那些能惠及更多 Git 用户的改进。

浙公网安备 33010602011771号