1. 一个反直觉的工程选择:让 AI 修改自己的源码
先说一个可能和多数人直觉相悖的事实:GitHub 这个承载了全球数亿个代码仓库的平台,其自身的代码库也面临着所有老系统都会遇到的麻烦——技术债堆叠、依赖版本过于陈旧、核心服务之间的耦合越来越深。维护团队每天都在和这些存量代码搏斗,而新功能的开发节奏一直被拖后腿。于是他们做了一个很激进的决定:把自家代码库的一部分交给 AI 来"重写",通过大批量生成 PR 的方式,在三周内合并了 128 个由 AI 辅助完成的 Pull Request,累计改动约 83 万行代码。
看到这个数字,很多人第一反应是"是不是 ChatGPT 直接吐出 83 万行代码,然后一股脑贴进去"。如果真这么干,代码库早就炸了。实际上,这 128 个 PR 背后是一套相当精细的工程流程,涉及任务拆解、上下文治理、编译与测试的自动化闸门、以及人与 AI 审查协作的新模式。每一个 PR 的改动量、边界和验收标准都是事先设计好的,AI 更像是流水线上一个不知疲倦但需要严格看管的操作员,而非拍板的设计师。
这个案例的参考价值并不限于 GitHub 一家。任何团队只要手里有一批 10 万行以上的存量代码,正在为依赖升级、API 迁移、框架换代而头疼,都能从中提炼出一套可复用的思路。这篇文章我会沿着这个项目的推进链条,逐个环节拆开讲清楚:为什么它敢让 AI 动源码,拆分 PR 的逻辑是什么,质量怎么兜底,三周时间线是如何编排的,以及这套玩法在什么条件下可以复制到你的项目里。
会涉及不少具体做法和判断依据,但不会把"AI 生成的代码能不能用"当成一个玄学问题来回答——用数据、流程和验证结果说话,比情绪化争论靠谱得多。
2. 从"人工迁移"到"AI 批量改造":这 83 万行代码的问题本质
2.1 存量代码升级的典型困境
GitHub 面对的存量代码,本质上是两类问题的叠加:
第一类是依赖陈旧的连锁反应。代码库使用的核心框架版本停留在一个相当古老的版本上,这个版本早已停止维护,又因为安全公告和兼容性要求不得不升级。可一旦升级核心框架,与之配合的周边库、工具链、自动构建脚本也必须一并调整。这些依赖像一张互相咬合的齿轮网络,单独动某一个齿轮,相邻的齿轮就会卡死。人工梳理这种依赖网络极其耗时,而且常常出现"昨天改好了三个文件,今天发现另一个模块的调用方式又变了"的情况。
第二类是跨模块的 API 表面迁移。旧框架的 API 在被调用时,参数结构、返回值格式、异常处理方式约定,散落在几十个乃至上百个文件中。每一个调用点看似孤立,改起来也不需要动太多脑子,但总数庞大。让资深工程师连续三周坐在那里机械地修改这种"有明确改法但没有智力挑战"的代码,是巨大的浪费,而且人恰恰在这种重复劳动中最容易疲劳走神,漏掉边界情况。
对于这类问题,传统做法是组织一个专项小组,按照模块边界分批迁移,每批走一遍"梳理调用点—修改—编译—测试—人工 review"的流程。整个过程通常以月为周期计算,而且会造成主干分支长时间处于半迁移状态,其他团队的开发工作不断被冲突打断。
2.2 为什么这个场景天然适合 AI
AI 代码生成模型在这个场景中的表现,远好于在"从零写一个分布式存储系统"这类开放式需求中的表现,原因是边界足够清晰、验收标准足够客观。
先看任务性质:API 迁移、依赖升级、废弃接口替换这类工作,输入是旧调用方式,输出是新的等价调用方式,过程高度程序化。模型的训练数据里存在大量同类迁移的样例,它在"见过足够多相似改法"的前提下,可以直接给出符合新 API 约定的代码。你可以把这一步理解为:把 80 万行代码当作训练好的翻译模型的源语言,目标语言是升级后的 API 规范——比自然语言翻译更简单,因为语法规则是确定的,编译器和测试套件就能当翻译质量裁判。
再看反馈回路。人工迁移一个文件后,要手动跑编译、跑单测,确认没问题再进入下一个文件。AI 迁移也一样,但它的迭代速度可以被工程化地推到极致——每个 PR 生成后自动触发 CI 流水线,编译错误和测试失败结果直接回传给生成模块,让模型在下一次生成中规避同类问题。这种"生成—验证—修正"的循环,正是机器学习模型最擅长的学习模式。人在这个回路里的角色被压缩到两种:设计任务边界,和处理机器无法通过的边缘案例。
最后是规模效应的区别。人工完成的迁移,经验和注意力是逐文件流失的;AI 生成的迁移,越到后面越能借助反馈积累避开常见错误模式。128 个 PR 能控制在三周完成,与其说是模型聪明,不如说是这个工作模式的迭代速度足够快。
2.3 先立规矩再放开手脚:边界划分原则
当然,AI 写代码的能力再强,也不能让它"自由发挥"去重构整个代码库。GitHub 这边的处理原则很值得借鉴:AI 的修改范围被严格限定在"同构迁移"范围内,即只改变调用的方式,不改变业务逻辑。
换句话说,凡是需要理解业务意图的改动——比如"这个功能在旧框架里依赖回调,新框架里要改成事件驱动,那业务行为要不要变"——都不在 AI 的决策范围内,必须由人工先给出标准改法。AI 只能在这种预先定义好的改法框架内执行大规模复制和替换。
这个边界看起来保守,实际上非常聪明。业务逻辑的改动需要人的判断,争议大、责任重;而迁移类改动是确定性工程,适合机器批量执行。两者一旦混在一起,review 的人就永远分不清改坏了是 AI 的锅还是当初业务设计就有问题。保持同构迁移,审查边界就非常清楚:新增代码和删除代码是不是一一对应,逻辑有没有多出来或者少掉,一目了然。
3. 128 个 PR 的拆解策略:怎么把一个庞然大物切得不重不漏
3.1 按依赖层级排序,而非按代码行数
83 万行代码分布在大量仓库和服务中,如果第一反应是"按文件数量均匀切 128 份",后患无穷。GitHub 团队采用的是依赖层级优先的拆解策略:先列出一张依赖关系拓扑图,找出那些被最多模块引用的底层库,从最底层开始迁移。
这个顺序很关键。在软件工程里,底层依赖是"牵一发动全身"的,它出问题,所有上级模块全都跟着报错。先把底层迁移完成,并且保证它稳定通过全部既有测试,之后上层模块的迁移就有了一份可信赖的新地基。反过来做的话,上层模块改好了,下一周底层一换,上层又要重新返工。
拆解出的每个 PR 也严格限制改动面积。128 个 PR 平均每个约 6 千行左右代码改动,但这不是指一次性生成 6 千行新代码,而是"修改涉及 6 千行"——很多情况下,其中一半是机械性的接口替换、签名变更,另一半是为了配合变更而微调的外部调用点。PR 保持小粒度,一是有利于 review,二是出问题时定位成本低,三是可以更快地暴露系统性错误,避免错误模式被复制到几十个 PR 里才发现。
3.2 把"先导 PR"作为样板书
项目启动阶段,团队并没有让 AI 同时开跑各种任务,而是先人工完成了一个小规模的先导 PR,覆盖典型的迁移路径。这个 PR 的规格是这样的:
- 选择底层依赖中的一个中等规模模块,包含约 20 个调用点,覆盖了三种最常见的 API 使用方式;
- 人工完成迁移后,配上详细的 PR 描述,重点写明三类信息:旧 API 到新 API 的映射规则、特殊场景的处理约定(比如回调改事件后的时序问题)、以及编译和测试的验证结果;
- 把这个 PR 作为后续 AI 生成的"风格参考"。
之所以要这个先导过程,是因为模型提示词写得再详细,也不如一个真实可运行的成品样例更有约束力。AI 在生成本文后续的 PR 时,参考的就是这个样板书中的映射规则和代码风格。如果有多种 API 使用方式,样例里没有覆盖到,AI 生成的代码很可能跑偏——所以先导 PR 选择的模块要足够典型,覆盖尽可能多的调用变体。
后来据团队复盘,这个先导过程大约占用了整个项目初期一周中的三分之二时间,但极大降低了后续批量生成阶段的纠错成本。这属于典型的"慢就是快",前期规则不清楚就匆忙让 AI 大规模产出,后面付出的返工代价会高出一个数量级。
3.3 上下文治理:如何避免 AI 迷失在代码海洋
市面上大多数 AI 代码工具直接面对单文件或单个仓库干活,改动范围相对可控。但当目标任务变成"跨 20 个仓库、修改 83 万行"时,最棘手的不是生成,而是上下文。模型的上下文窗口装不下整个代码库,强行把相关代码全部塞进去,既浪费 token,又会让模型在无关细节中迷失重点。
GitHub 的做法是给每个 PR 任务配一个"上下文包"。这个上下文包不是随机挑选的代码文件,而是根据依赖关系精确计算出的最小集合:
- 本 PR 任务涉及的所有源文件;
- 这些文件直接调用的依赖接口定义(不需要完整实现体,只需要签名和类型声明);
- 本任务需要迁移到的目标 API 的参考文档和样例片段;
- 以及与本次迁移相关的测试文件,确保生成的代码在逻辑上空跑时能配对测试用例。
这个最小集合的构建有点类似编译器里的"按需引入"。上下文包里的代码量控制在模型可接受的范围,同时保证生成结果所需要的全部约束都在场。整个过程中最考验功力的地方就在于识别哪些文件可以放心地从上下文包里剔除——这需要在基于依赖关系做可达性分析的基础上,再结合对目标框架的理解来判断。依赖分析工具能算出相关文件的完整列表,但最终删掉哪些巨量的"顺带引用"还是得人工拍板。
3.4 大量生成后的人工分组 review
128 个 PR 三周内完成,平均每天约 6 个 PR 产出,这个频率放到一个正常开发团队里已经相当高了。但如果牵头人每天都要逐个打开 PR 检查每一行代码,人力完全跟不上。所以 review 也做了分层次设计:
第一层是机器把关。编译检查和全套测试是硬门槛,这个没过的话 PR 根本无法合入。第二层是抽样人工 review。每个批次 PR 中,人工会挑若干有代表性的做全量代码审查,重点看那些涉及特殊边界处理的文件,而不是均匀撒网。第三层是模式验收。项目负责人每天会进行一次错误聚类——把当天产生的所有 review 意见按错误类型归类,如果发现某一类错误频繁出现,就回到提示词或者先导样例中补充对应规则,下一批量生成时就能系统性地规避。
这种"人抽查 + 机器全量 + 错误聚类反馈"的组合,让质量保障真正做到了"越到后期越稳定"。
4. 质量怎么守:编译、测试、人工三重闸门
4.1 把"AI 生成的代码能不能用"变成一道计算题
圈里对 AI 写代码的质疑,大多集中在"AI 生成代码可能逻辑正确但语义偏颇"这个点上。这个担忧在从零开发场景下是成立的,但在同构迁移场景下其实可以被大幅消解——因为存在客观的判定基准:迁移前后功能等价。
GitHub 的做法是把等价性测试做成自动化流水线的核心部分。每个 PR 生成后,第一关是编译能否通过。编译器对语法、类型、接口签名进行严格校验,AI 如果犯了低级错误,在这个环节就直接打回,压根不浪费人类审查者的时间。第二关是现有的全部单元测试和集成测试。这部分测试是在迁移发生之前就已经存在的,它们代表了系统当前的既定义务。迁移后的代码改动只是替换接口调用,不改业务逻辑,那么这些测试一个都不应该失败——凡是失败的,必须给出合理解释,否则 PR 不能合入。
这个方法听起来简单,但它有一个隐藏前提:存量测试套件必须足够健康。如果一个代码库本身测试覆盖率低下,或者现有测试里已经有一堆长期处于失败状态的用例,这套闸门就毫无意义。GitHub 的代码库在这点上基础相对扎实,这也反过来解释了为什么他们有底气推进这种大规模的 AI 改造——自动化验证基础强的系统,才敢让机器动手。
4.2 特殊边界情况的处理规则
迁移过程中,总有一部分测试用例在改动后必然会失败——因为旧测试本来就是针对旧 API 行为设计的,新 API 语法变了,部分用例需要同步更新。这里如果处理不当,会出现一个经典陷阱:AI 为了图省事,直接改测试断言去适应新实现,相当于"改答案去凑题目",这是绝对不可接受的。
GitHub 团队的策略是:测试文件的更新也必须走人工明确的规则指引。AI 只被允许修改调用方式和构造参数的方式,测试断言中期望的结果值不被允许改动。如果新 API 放返回值的语义发生了变化,导致既有断言必然失败,那就需要人工介入判断——到底是迁移逻辑有问题,还是新 API 打破了兼容语义。这个判断已经超出模型能力,必须交给熟悉业务的工程师完成。
整个过程里我最认同的是他们对"模棱两可"的零容忍态度。一次 review 中如果出现 AI 某个改动行为原因不明的状况,工程师必须追查到底,不允许出现"这边看起来差不多就行"的情况。因为模型生成代码的潜在缺陷往往是系统性的,放掉一个模糊点,可能意味着同一模式已经在几十个文件中潜伏着。
4.3 PR 描述与变更记录的隐性价值
128 个 PR 的合入不只是代码层面的变更,它还制造了一份极其完整的迁移文档。每个 PR 的描述里记录了改动背景、涉及的服务、测试验证方式,甚至包括迁移过程中哪些规则被更新过、为什么更新。这份记录的价值在项目结束后才慢慢显现——后续任何人遇到类似迁移问题,直接搜 PR 记录就能复现完整的决策链路。
另一个容易被忽略的隐性价值是 review 效率的持续优化。项目团队把 review 历史积累产生的常见错误清单整理成了结构化提示词模板,越到后面,生成的 PR 初始质量越高。从数据上看,后期的 PR 平均 review 轮次比初期显著减少,一次通过的占比也大幅提升。这充分说明这套"生成—反馈—规则更新—再生成"的闭环真的在工作,而不是靠运气一个个改对的。
5. 三周时间线编排:快节奏下的节奏感与回撤机制
5.1 第一周:铺地基,跑流程
整个项目的第一周并不是大规模产出的时候。公开的一些过程资料显示,这一周的核心在于把先导 PR 打磨到可以当范例的程度,并把 CI 流水线中新引入的 AI 生成校验步骤全部跑通。同时,团队会完成一个关键分工——决定哪些仓库先做、哪些后做,并和各个下游业务的 owner 确认迁移顺序。这一步如果省了,后面很容易出现"PR 合并完,某个隐藏下游模块编译失败还要紧急回滚"的被动局面。
第一周接近结束时,项目组通常只合并了少量先导 PR,数量可能只有个位数。但所有参与者的信心已经建立起来:人力、流程、验证手段全部就绪,剩下的事情就是顺着流水线往下推。
5.2 第二周:批量产出的加速期
进入第二周,批量生成才真正开启。基于第一周打磨好的样例和规则库,AI 开始在多个仓库并行生成 PR。此时每天的产出从个位数迅速跃升到两位数。团队节奏也调整为:上午查看机器筛选后失败的任务并快速修复,下午集中 review 通过编译与测试的 PR,傍晚汇总当天的错误聚类和规则更新清单。
这个环节出现最多的并不是代码生成问题,而是跨仓库协调。上游仓库的 PR 合入后,下游仓库的依赖同步需要时间,部分并联任务可能因为等待上游而阻塞。解决方案是把依赖链条长的任务尽量安排在线性通道上串行推进,而把相互独立的仓库拆到不同通道并行——调度算法不复杂,但需要有人在第一天就把这个依赖矩阵画明白。
5.3 第三周:收尾与顽固问题攻坚
最后一周,剩余的工作量逐渐收窄,但剩下的任务往往不是之前流水线能轻松处理的部分。这些顽固问题大概有三类:
第一类,老代码中存在大量重复逻辑和死代码,AI 在迁移时不知道是应该一并清理还是保持原样。统一约定是:不夹带无关重构,把清理留到后续专项处理。这个约定避免了很多让 review 争论不休的情况。第二类,某些模块的测试覆盖率本身极低,AI 改完之后没有足够的测试来验证语义是否真的没变。这种模块只能靠额外的人工审查兜底。每一个这样的模块,都需要领域工程师仔细检查 diff 里的逻辑对应关系,才能确认迁移安全。第三类,三方依赖升级引起的编译链变化,超过了 AI 能消化吸收的范围。这种情况下最稳妥的办法不是逼 AI 硬扛,而是把这类情况单独拎出来,走传统的人工升级路径,留到项目之后另行解决。
这个收尾阶段让我最感慨的一点是:项目方没有为了追求"100%由 AI 完成"这个 KPI 而死撑。能由 AI 批量处理的部分大规模自动化,不能的则坦率地交给人工。三周完成 128 个 PR 固然亮眼,但真正健康的度量指标是"在当前约束条件下系统达到了最优的自动化覆盖率",而不是"所有改动都必须由 AI 生成"。
5.4 进度度量的三个关键信号
整个项目周期的进度不是靠"PR 合入数量"单指标推动的,团队还同时盯着另外两个信号:
信号一:编译失败率的变化趋势。如果随着规则库越来越完善、参考样例越来越丰富,编译失败率应该持续下降。如果某天失败率反而反弹,通常意味着新接触了一个之前没见过的 API 变体,需要专门补规则。信号二:人工 review 的非机械性意见占比。机械意见(比如格式、命名、基本接口签名错误)占比越高,说明规则还应该继续沉淀;机械意见减少、非机械性意见增多,说明 AI 已经把能学的都学到了,剩下只剩真正需要人判断的部分。信号三:延期任务的 reason 分布。每周任务没能按时合入的原因如果是"上游依赖未就绪"这类协调问题,说明调度策略还有优化空间;如果集中出现在"测试断言语义冲突",则说明业务逻辑的迁移路径本身没设计好。
这三个信号组合起来,可以清晰判断"项目进行到哪了、接下来重点是哪里"。单纯盯着 PR 数量只会让人在顺境中盲目乐观,逆境中慌忙救火。
6. 这套玩法能复制到哪一步:规模、条件与分批推进的思路
6.1 不是所有代码库都适合 AI 批量重写
写到这里,必须给跃跃欲试的读者浇一盆客观的冷水:GitHub 的成功建立在几个相对苛刻的前提之上。复制这套方案前,建议先对着这个清单自查:
- 代码库的依赖关系是否清晰可解析?模块边界含糊、大量循环依赖的代码库,AI 生成的迁移很容易让问题雪上加霜。
- 测试套件覆盖率是否足够?至少核心路径要有较高覆盖。没有自动化验证兜底,AI 的大规模产出就约等于往生产环境扔炸弹。
- 存量代码是否已经在稳定运行?如果代码库本身处于频繁的业务迭代之中,迁移过程中不断有新改动汇入,会让 AI 的上下文包迅速过期,生成的 PR 大量作废。
- 团队是否有足够的 review 人力储备?128 个 PR 背后的 review CPU 消耗是巨大的,小团队如果一边做业务一边处理这堆 PR,大概率会被拖垮。
6.2 小规模团队的"简化版复刻"
规模小一点的团队,未必用得上 128 个 PR 这种量级,但完全可以借鉴其核心思路,做一个简化版:
把目标从一个庞大的代码库收缩到一个具体的服务模块,或一类有明确图纸的 API 接口迁移。先人工做一个标准样例 PR,让 AI 照猫画虎,批量生成后续改动。每一批生成结果都走同一套"编译校验 + 测试验证 + 人工抽查"的闸门。不需要严格的 83 万行目标,哪怕只是把几千行四处散落的废弃调用点改干净,也能体会到这套流程和"几个工程师没日没夜手动改"之间的效率差异。
技术选型上,GitHub 官方文档和技术博客里提到他们主要使用了内部的代码生成基础设施,配合自家 Copilot 的能力。中小团队没有这种基础设施也不影响,主流的几个 AI 编程工具都支持多文件编辑、批量提交,可以在有限上下文的约束下完成类似的任务编排。核心还在于流程设计——怎么拆任务,怎么定规则,怎么验证结果。工具永远是辅助,流程才是保障。
6.3 与现有研发流程的融合方式
最后一点想单独展开,因为它被很多人忽视了:AI 重写代码这事,不是"开一个三周临时项目,干完拉倒"这么简单。它最好能嵌入到团队常态化维护工作的节奏里。
比如,依赖升级这类反复出现的任务,可以在每次升级时都跑一遍"样例 PR + AI 批量生成 + CI 验证"的流程,而不用每次都当做大项目来立项;又比如,AI 生成过程中的规则库和错误清单,可以沉淀为团队内部的知识库,无论哪一轮迭代都能复用。GitHub 这次项目最深远的意义恰恰在于它验证了这种模式的稳定性,真正让"AI 不是一次性帮手,而是持续参与代码维护协作的环节"从口号变成了被验证过的实践。
从这个角度回看整个项目,衡量它的标准不应该只是 128 个 PR 或 83 万行代码,而是一整套可被移植、可被迭代、可被复用的工程方法论。