前言我以前最怕看到那种几千行的 Pull Request。不是因为代码一定难而是因为审查这类 PR 很难进入状态。文件太多改动太散前半段还在看数据结构下一段已经跳到 UI再往后又开始改测试和构建脚本。审查者看着看着就会失去上下文提交者也只能等着别人抽出一整块时间。GitHub 在 2026 年 4 月公开了 Stacked PRs 的 private preview。它解决的正是这种大 PR 堆在一起的问题。一个大功能不再一次性塞进一个 PR而是拆成一组有顺序的小 PR。底层 PR 先承接基础改动上层 PR 再继续往前开发整个链路在 GitHub 里形成一个 stack。这个工作流并不新。Meta、Google 这类公司内部很早就习惯用 stacked diff 或类似模式处理大规模代码审查。Facebook 当年的 Differential也是围绕代码审查等待时间和大变更管理做出来的工具。GitHub 这次做的事情是把这套工作方式带进普通 GitHub PR 流程里让它不再只属于有自研工具的大团队。我更关心的是它对日常开发节奏的影响。现在 AI 编程工具会更快生成大量代码PR 的体积只会越来越大。如果审查方式不跟着调整团队会很快进入一个很尴尬的状态代码产出速度上去了合并和审查却被堵住了。Stacked PRs 的价值就落在这里。它让一个大改动拆成多个能审、能测、能合并的小改动开发者可以继续推进后续层审查者也可以按顺序理解每一层代码。一、大 PR 的问题不只在行数一个 2000 行 PR 最大的问题不是它看起来吓人而是它把太多决策压在了一次审查里。假设我要开发一个结算功能。最常见的做法是从main拉出一个feature/checkout分支然后在里面做完数据库 schema、API、业务校验、前端页面、测试和文档。最后打开一个 PR请同事一次性审查。这个 PR 可能会同时包含这些内容。改动内容审查者真正需要关注的点数据库 schema字段是否合理约束是否够用迁移是否安全API 接口参数校验、错误处理、权限边界结算逻辑金额计算、优惠规则、库存扣减UI 页面交互流程、状态提示、异常分支测试代码覆盖路径、边界输入、回归风险文档说明使用方式、接口契约、迁移说明这些内容都在一个 PR 里时审查者需要不停切换思维模型。刚看完数据库设计还没完全理解就要去看 APIAPI 还没看完又进入前端交互。最后常见结果是大家只对明显问题留言真正需要仔细确认的逻辑细节反而被跳过去。大 PR 还会放大等待时间。审查者知道这不是十分钟能看完的改动就会把它往后放。提交者等不到反馈又继续在同一个分支上补功能。等审查真正开始时PR 已经比提交时更大了。我自己处理这类改动时会明显感觉到两个阻塞点。第一个阻塞点在审查。PR 越大审查者越难找到合适时间也越容易只看局部。第二个阻塞点在后续开发。前面的基础代码还没有合并后面的功能已经依赖它。继续做会让分支越来越厚停下来等又会打断节奏。Stacked PRs 解决的就是这两个阻塞点。它让开发者在等待底层 PR 审查时继续写上层代码也让审查者每次只处理一个小范围内的改动。二、Stacked PRs 到底怎么组织Stacked PRs 的基本结构很简单。每个 PR 仍然是普通 PR只是它的目标分支不一定是main也可以是另一个 PR 对应的分支。还是用结算功能做例子。main ↑ PR1 feature/checkout-schema ↑ PR2 feature/checkout-api ↑ PR3 feature/checkout-ui第一层feature/checkout-schema基于main只处理数据结构。第二层feature/checkout-api基于第一层分支处理接口和业务逻辑。第三层feature/checkout-ui基于第二层分支处理页面和交互。每个 PR 都只展示自己这一层新增的 diff。审查 PR2 时不需要重新看 PR1 的 schema 改动审查 PR3 时也不需要把 API 代码再看一遍。这个差异很关键因为它让大功能变成了一个可按顺序理解的代码链。GitHub 这次加入原生 Stacked PRs 支持后重点不只是允许目标分支指向前一个 PR。传统 GitHub 早就可以手动创建这类链式 PR真正麻烦的是后续管理。比如怎么查看整条 stack怎么确认每一层 CI 状态怎么处理下层 PR 修改后上层分支的 rebase怎么让 branch protection 按最终目标分支判断。新的 Stacked PRs 会在 GitHub UI 里展示 stack map审查者可以直接看到当前 PR 位于哪一层下面还有哪些前置 PR上面还有哪些后续 PR。gh stackCLI 则负责处理本地分支、级联 rebase、推送和 PR 创建这些细节。我会把它理解成两层能力。层级以前手动能不能做GitHub 原生支持补上的内容分支链可以手动做仍然基于 Git 分支和 PRPR 目标分支可以手动选择GitHub 知道这些 PR 属于同一个 stack审查导航基本靠 PR 描述手写UI 展示 stack map 和层级状态rebase 维护需要手动逐层处理CLI 和 UI 支持级联 rebase合并顺序靠团队约定可以合并整个 stack 或其中一部分规则校验容易受直接 base 影响按最终目标分支理解规则和 CI这也是 GitHub 现在做 Stacked PRs 的意义。手动 stacked branch 并不稀奇真正影响团队采用的是工具摩擦。只要每次修改底层 PR 都要自己逐层 rebase很多团队试两次就会放弃。三、手动也能做只是维护成本很高在没有启用 GitHub Stacked PRs private preview 的仓库里仍然可以用标准 Git 和 GitHub 手动模拟这个流程。先从main创建第一层分支。gitcheckout maingitpullgitcheckout-bfeature/checkout-schema# 修改数据库 schemagitadd-Agitcommit-madd checkout schemagitpush-uorigin feature/checkout-schema在 GitHub 上创建 PR 时目标分支选择main。接着不要回到main直接从当前分支继续创建第二层。gitcheckout-bfeature/checkout-api# 实现结算 APIgitadd-Agitcommit-madd checkout apigitpush-uorigin feature/checkout-api这次创建 PR 时目标分支选择feature/checkout-schema。第三层继续基于第二层。gitcheckout-bfeature/checkout-ui# 完成结算页面gitadd-Agitcommit-madd checkout uigitpush-uorigin feature/checkout-ui这个 PR 的目标分支选择feature/checkout-api。到这里一条手动维护的 stack 就建立起来了。PR1 只看 schemaPR2 只看 APIPR3 只看 UI。审查者可以从底层往上看也可以先看某一层的实现方向但真正合并时要尊重依赖关系。麻烦出现在反馈修改上。假设审查者在 PR1 里要求调整 schema 字段。你回到feature/checkout-schema修改并推送以后PR2 和 PR3 仍然基于旧的 PR1 提交。这个时候上层分支需要跟着更新。gitcheckout feature/checkout-schema# 修改 PR1gitadd-Agitcommit-madjust checkout schemagitpushgitcheckout feature/checkout-apigitrebase feature/checkout-schemagitpush --force-with-leasegitcheckout feature/checkout-uigitrebase feature/checkout-apigitpush --force-with-lease三层还能接受五层、七层就会开始烦。更麻烦的是其中某一层 rebase 出现冲突后面的分支也要继续跟着处理。这个过程本身不难但会消耗注意力而且很容易在赶需求时处理错分支。Git 2.38 之后rebase --update-refs能减轻一部分维护成本。它可以在 rebase 时自动更新指向被改写提交的分支引用适合处理一组互相依赖的 stacked branches。gitconfig--globalrebase.updateRefstruegitcheckout feature/checkout-uigitrebase main --update-refs这里要注意一个细节。通常需要在 stack 顶部的分支上执行 rebase让 Git 能看到整个链路里需要更新的引用。如果你只在中间层随手执行结果可能和预期不一致。--update-refs很适合熟悉 Git 的开发者但它仍然没有解决 GitHub UI 层面的导航、状态展示和合并管理。真正让团队更容易采用 Stacked PRs 的还是 GitHub UI 和gh stackCLI 对整条 stack 的识别。四、gh stack把分支链变成一组可操作对象GitHub 这次提供的gh stack本质上是一个 GitHub CLI 扩展。它把原来手动处理的分支链包装成一组可以初始化、添加、推送、提交 PR、查看和同步的操作。安装方式很直接。gh extensioninstallgithub/gh-stack然后可以在本地启动一条 stack。gh stack init继续添加下一层分支。gh stackaddapi-endpoints推送整条 stack。gh stack push查看当前 stack。gh stack view创建一组 PR。gh stack submit从命令上看它并没有发明新的版本控制模型。底层仍然是 Git 分支、提交和 PR。它的价值在于把这些分散动作组织起来减少手动维护链式分支时的错误。尤其是sync这类操作能处理 stack 里的级联 rebase。对团队来说这类能力比创建 PR 本身更重要。因为创建 stack 只发生一次后续修改和同步会发生很多次。GitHub 还给gh stack准备了 AI agent integration。安装对应 skill 以后AI coding agent 可以理解 stacked PRs 的工作方式帮助把大 diff 拆成一组 PR或者从任务开始就按 stack 开发。这个方向其实很符合 2026 年的开发现实。AI 能生成更多代码也会带来更大的 diff。团队不可能让审查者面对一堆 AI 生成的大 PR只靠人工耐心硬看。更合理的方式是让 agent 在生成阶段就把变更拆成层次清楚的小 PR让人类审查者按层理解。五、合并策略要提前和团队说清楚Stacked PRs 不是单人技巧。只要进入团队协作就会碰到合并策略、分支保护、CI、merge queue 和审查习惯。我会先确认三个问题。第一团队是否允许 PR 的 base 分支不是main。有些团队的检查脚本、自动化工具或开发规范默认所有 PR 都指向主干分支。Stacked PRs 需要让 PR2 指向 PR1 的分支PR3 指向 PR2 的分支团队工具要能接受这种结构。第二团队是否强制 squash merge。手动 stacked branch 最怕中间层被 squash 后破坏提交关系。GitHub 原生 Stacked PRs 对整条 stack 有更多识别能力但如果团队仍然混用各种合并方式容易让上层 PR 出现不必要的冲突。刚开始试用时我会先在一个小仓库里验证团队当前的 branch protection、merge queue 和合并策略再推到主仓库。第三CI 应该按哪一层执行。理想情况下每个 PR 都要独立跑测试并且要按最终目标分支理解规则。GitHub 原生支持的价值之一就是它知道 stack 的最终落点不只是看当前 PR 的直接 base。如果团队刚开始尝试我不建议一上来把所有大功能都改成 stack。更稳的做法是选一个范围明确的功能试一次比如一次接口重构、一个页面改版、一个小型模块拆分。用 3 层以内的 stack 先跑通流程再讨论团队规范。一个比较舒服的拆法大概是这样层级PR 内容审查重点PR1类型定义、schema、底层工具函数数据结构和边界PR2服务层、API、业务逻辑状态流、错误处理、权限判断PR3页面、交互、测试用例用户路径、异常提示、回归覆盖这样拆出来以后每一层都能独立讨论又不会把功能切得太碎。太细的 stack 也会带来反作用审查者需要不断切换 PR反而增加沟通成本。六、哪些场景值得用 Stacked PRsStacked PRs 适合有依赖关系的大改动。它不是为了把所有 PR 都拆小也不是为了追求形式上的每 200 行一个 PR。我会优先在下面几类场景里使用。6.1 大功能分层开发一个功能天然可以拆成基础层、服务层、界面层、测试层就很适合 stack。比如电商结算、订单重构、会员订阅、权限系统、搜索筛选、数据导入导出。这类功能如果一次性提交审查者会在不同抽象层之间来回跳。拆成 stack 后底层设计可以先被确认上层实现再继续推进。6.2 重构和功能改造混在一起很多改动最难审查的地方是重构和新功能混在一起。比如先抽出一个 service再基于这个 service 增加新能力。如果这两个动作在同一个 PR 里审查者很难判断哪些是无行为变化重构哪些是新功能逻辑。Stacked PRs 可以把重构放在底层 PR把功能放在上层 PR。这样审查时就能先确认重构有没有改变行为再看功能实现是否正确。6.3 AI 生成的大 diffAI 生成代码以后经常会一次性改很多文件。它可能顺手调整组件、类型、样式、测试和工具函数。代码能跑但审查者很难知道从哪里开始看。这个时候可以要求 AI 先把 diff 拆成 stack。第一层只放类型和基础工具第二层放业务逻辑第三层放 UI第四层放测试。人类审查者仍然要负责判断但审查入口会清楚很多。6.4 不适合的场景有些改动不需要 stack。比如修一个 typo、改一个配置、补一个测试、修一个小 bug普通 PR 更直接。为了 stack 而 stack会增加不必要的分支和合并管理成本。我也不建议把一个没有明确依赖关系的需求硬拆成 stack。Stacked PRs 的前提是层与层之间有清楚的顺序。如果只是几个无关小改动把它们分别开成普通 PR 就够了。七、我会怎么落地这套流程如果我在自己的项目里引入 Stacked PRs会先定几条简单规则避免它变成新的流程负担。第一每个 PR 要能用一句话说明自己这一层解决什么问题。如果一句话说不清说明这一层可能还需要再拆或者拆分边界不对。第二stack 深度先控制在 3 到 5 层。三层最容易理解五层已经需要比较好的命名和描述。超过五层以后任何底层修改都会影响一串分支管理成本会上来。第三PR 标题要带层级感。比如[checkout 1/3] add checkout schema [checkout 2/3] add checkout service [checkout 3/3] add checkout page即使 GitHub UI 已经能显示 stack map标题里的层级仍然有用。它能让通知列表、邮件、Slack 消息里也保留上下文。第四PR 描述里写清楚前置关系和审查建议。比如 PR2 可以写一句先看 PR1 的 schema再审查当前 API 层。这样审查者不会从中间层误入整条链。第五底层 PR 尽早提交审查。Stacked PRs 的优势在于开发可以继续往上走但底层设计如果一直不被确认上层代码会积累风险。越底层的 PR越应该尽早发出来。第六合并前跑一次完整同步。无论使用gh stack sync还是 Git 的--update-refs合并前都要保证上层分支基于最新底层结果。这个动作可以减少合并队列里的意外冲突。对小团队来说这些规则已经够用。工具只是降低摩擦真正影响结果的还是拆分能力。一个 PR 应该拆在哪里、哪些变更应该放一起、哪些反馈会影响上层代码这些仍然需要开发者自己判断。总结GitHub Stacked PRs 让我最有感触的地方是它把大改动拆小这件事做成了平台能力。过去这套工作流需要 Phabricator、Gerrit、Graphite 或团队自己的脚本来维护现在 GitHub 开始在 PR UI、CLI、branch protection、CI 和 merge queue 里理解 stack。它不会自动让代码审查变轻松。拆得太碎、命名混乱、底层设计反复变化仍然会让团队难受。它真正适合的场景是那些本来就有层次的大改动先改基础结构再改服务逻辑再改界面和测试。我会把它当成 AI 编程时代更需要的工程习惯。代码生成速度越快越不能把所有改动塞进一个巨型 PR 里等人慢慢审。把变更拆成能理解、能审查、能逐层合并的 stack才更接近团队真正能消化的节奏。如果现在还没有拿到 GitHub Stacked PRs private preview也可以先用手动目标分支、gh-stack思路、Graphite 或git rebase --update-refs练起来。工具会继续变化但把大改动拆成小层次的能力值得尽早变成团队习惯。