在大规模代码变更的开发过程中,传统单一 Pull Request 模式常面临 reviewer 负担过重、合并冲突频发、迭代周期冗长等问题。Stacked PRs(堆叠式 PR)作为一种工程实践,将完整特性拆解为若干相互依赖的小型 PR,形成审查链式结构,实现增量式代码集成与快速反馈闭环。
依赖分组策略:从单体到链式
Stacked PRs 的核心思想是将一个完整特性按照依赖关系拆分为多个层级。分组原则应遵循「自底向上」顺序:底层 PR 实现基础设施或核心数据模型,中层 PR 提供业务逻辑,上层 PR 完成界面展示或端到端集成。以一个用户系统为例:PR1 负责数据库迁移,PR2 基于 PR1 实现 API 端点,PR3 依赖 PR2 完成前端交互。每个 PR 的代码行数建议控制在 200 至 400 行之间,确保 reviewer 能在 15 分钟内完成审阅。
依赖关系的建立通过 Git 分支拓扑实现。具体而言,PR1 基于 main 或 develop 分支创建;PR2 基于 PR1 的分支创建,而非直接基于 main;PR3 则基于 PR2 的分支。这种链式分支结构确保了代码变更的传递性:下游 PR 天然包含上游 PR 的所有修改。
串行审查流程设计
串行审查是 Stacked PRs 的必然选择,因为下游 PR 的代码正确性依赖于上游 PR 的合并状态。流程设计需明确以下参数:上游 PR 合并后,下游 PR 的基线自动更新;审查过程中若上游 PR 需要修改,则该修改需先于下游 PR 完成。审查优先级遵循「从底向上」原则,reviewer 从链底 PR 开始,逐层向上推进。
为提升串行审查效率,建议在每个 PR 的描述中明确标注其在栈中的位置。例如,PR 标题可采用「[Stack 2/4] API 变更」格式,并在描述中附加完整栈的链接列表。GitHub 官方支持通过 Draft PR 标识未就绪的变更,团队可据此区分「待审查」与「草稿」状态。
工具链选型与工程参数
目前主流工具包括 ghstack、stack-pr 和 Graphite。ghstack 由 Facebook 工程师 Edward Yang 维护,通过 Python 脚本实现本地 Git 堆栈与 GitHub PR 的双向同步,其核心参数包括ghstack --sync用于同步栈状态,ghstack --push推送所有待审查 PR。stack-pr 是 Modular 公司开源的工具,采用 TypeScript 编写,提供更简洁的 CLI 接口,默认配置下每个 PR 的标题会自动包含其在栈中的序号。
若团队偏好轻量化方案,亦可采用纯 GitHub 原生方式:手动创建链式分支,使用 Draft PR 标记状态,通过 PR 描述中的链接建立依赖可视化。关键参数包括:分支命名规范(如feature/user-api-1, feature/user-api-2)、PR 模板中的栈描述字段、CI 流水线中的栈健康检查(验证下游 PR 的上游依赖是否已合并)。
监控与回滚策略
工程实践中需关注两个监控点:栈的完整性检查与合并窗口控制。可在 CI 中配置自动化校验脚本,确认每个 PR 的 base 分支与上游 PR 目标分支一致,避免基线漂移导致的隐性冲突。若上游 PR 合并后下游 PR 出现不可调和的冲突,建议采用「整体回滚」策略:对整个栈执行交互式变基(git rebase -i),在编辑器中调整上游 PR 的修改后重新导出。
资料来源:本文技术细节参考 ghstack 官方文档与 Modular 公司 stack-pr 发布公告。