Skip to main content

关于堆叠式拉取请求

将大型代码更改分解成一系列较小的依赖拉取请求,你可以独立查看和合并。

注意

此功能以公共预览版提供,可能会发生更改。

关于堆叠式拉取请求

堆叠拉取请求是同一存储库中的两个或多个拉取请求,其中:

  • 第一个(也就是最底层的)拉取请求以该堆栈的主干为目标——通常是你的仓库的默认分支,例如 main,不过也可以是任意分支,例如发布分支。
  • 每个后续拉取请求都以下方拉取请求的分支为目标。
   ┌── feat/frontend     → PR #3 (base: feat/api-endpoints)  ← top
  ┌── feat/api-endpoints → PR #2 (base: feat/auth-layer)
 ┌── feat/auth-layer     → PR #1 (base: main)               ← bottom
main (default base branch)

堆叠分支形成一条依赖链,其中每个分支都建立在其下方分支之上。 基础性更改(如共享类型和数据库架构)位于较低分支中,依赖于它们的代码(如 API 路由和 UI 组件)位于更高的分支中。

堆栈中的每个拉取请求都表示一个离散的、可查看的一个或多个提交更改。 你可以分别审查和迭代每个拉取请求,而每个拉取请求只会显示其所在层的差异,以及其分支与下一层分支之间的更改。

关键原则: 如果一个层中的代码依赖于另一层中的代码,则依赖项必须位于同一分支或较低分支中。 当你开始处理一项基于到目前为止已完成工作的不同任务时,请创建一个新分支。 例如,当你从后端工作切换到前端工作、从核心逻辑转到测试,或者当前分支已经足够大,可以进行评审时。

为何使用 GitHub 堆叠式拉取请求

完成一项更改后,直接进行下一项

堆叠拉取请求允许在仍处于打开状态的拉取请求的基础上打开一个新的拉取请求。 在大型项目中,下一次更改可能取决于尚未合并的工作。 你无需等待其合并完成,使用堆栈时可以继续构建。

当堆栈中的每个拉取请求包含一个重点更改时,审阅者将看到每个层的小差异,而不是大型拉取请求。 较小的拉取请求审查起来更快,不太可能被草草审阅,也不太容易因搁置过久而产生合并冲突。

适合大规模开发

一次生成大量代码(通常使用 AI 代理)时,堆栈会为每个更改提供一个可去的地方。 代理完成一个任务,然后启动生成它的下一个任务。 该顺序正好对应于一个堆栈结构:每项任务一个拉取请求,且每个拉取请求都基于其下方的那个请求。 堆栈允许显式记录这些依赖项,而不是将不相关的更改合并到单个分支中。

在 GitHub 中使用堆叠式拉取请求的优势

如果没有堆叠式拉取请求,将一项大型更改拆分为多个较小且相互依赖的拉取请求会增加额外工作量:

  • 分支管理。 在相互依赖的拉取请求之间进行变基并保持分支同步,既繁琐又容易出错。
  • 规则和 CI。 分支保护规则和 CI 检查通常只会针对链条中最底部的拉取请求触发,因此很难了解其余拉取请求的实际状态。
  • 查看上下文。 脱离其余变更栈的上下文来审查单个更改,可能会降低评审质量。

堆叠式拉取请求通过将一连串拉取请求作为一个相互关联的整体来处理,同时让每一层都保持小而聚焦,从而解决这些问题。

变基

在使用堆栈时,变基是最棘手的部分,而 GitHub 会自动处理这一过程。 您可以从拉取请求触发服务器端级联变基,或者在 GitHub CLI 中使用 gh stack 扩展在本地运行级联变基。 在堆栈底部合并拉取请求时,其余分支会自动重新定基,以便下一个拉取请求面向默认基分支。

可在何处使用堆叠式拉取请求

可在以下位置使用堆叠拉取请求:

  • GitHub CLI
  • GitHub 网站
  • GitHub Mobile
  • 通过 Webhook、REST API 和 GraphQL 进行编程支持
  • 对于代理,通过 gh-stack 技能

注意

  • 堆积拉取请求要求所有分支都位于同一存储库中。 不支持跨分支堆栈。
  • 不支持堆叠拉取请求 GitHub Desktop。

在 GitHub CLI 中

GitHub CLI 中的 gh stack 扩展负责处理本地开发工作流。 您可以按正确的依赖顺序创建和跟踪分支,使分支保持变基状态,推送分支,创建并关联拉取请求,以及在各层之间导航。 请参阅“堆积拉取请求 CLI 命令”。

在GitHub网站上

当拉取请求是堆栈的一部分时,你将看到:

  • 位于拉取请求顶部的堆栈图标 ,旁边带有一个数字,用于指示你当前查看的是哪一层。
  • 堆栈映射显示在合并框中。 它显示堆栈中的每个拉取请求及其状态,并允许你单击一次导航到任何层。 主干分支(默认基础分支)位于最底部,堆栈中的每个拉取请求都以下方那个拉取请求所在的分支为目标。

通过 Webhook、REST API 和 GraphQL 进行编程支持

堆积拉取请求以编程方式可用,因此你可以将它们集成到自己的工具、自动化和仪表板中:

  • Webhookspull_request 事件负载中包含一个 stack 对象,因此,当拉取请求加入、在堆栈内移动或离开堆栈时,您的自动化流程便能作出响应。
  • REST API 读取拉取请求的堆栈成员身份,并提供用于列出、创建、扩展和解散堆栈的终结点。
  • GraphQL API 在拉取请求上公开只读 stack 字段,用于查询堆栈及其拉取请求的位置。

规则、CI 和合并

规则和 CI 强制执行

堆叠式拉取请求支持 GitHub Actions 工作流。

堆栈中任何拉取请求的合并要求通常由底部拉取请求的基分支 main确定。

  • 分支保护规则(如 CODEOWNER 审批)在堆栈中的每个拉取请求上强制实施,即使是不直接面向默认分支的中间堆栈拉取请求。
  • 默认分支上拉取请求触发的 CI 检查会针对堆栈中的所有拉取请求运行,而不仅仅是底部请求。

这可确保堆栈的每个层都满足相同的质量条,然后才能合并。

合并

您可以合并整个堆栈、单个拉取请求,或合并跨多个拉取请求的部分堆栈。 整个堆栈不需要一次合并,但拉取请求必须从下到上合并。

  • 通过合并最上方的拉取请求,一次性合并整个堆栈。 以下每个拉取请求都附带它。
  • 通过合并中间堆栈拉取请求合并堆栈的一部分。 它下方的拉取请求也合并,上面的拉取请求保持打开状态,并自动重新定位堆栈的基础分支。

堆栈支持合并提交、squash 和 rebase 合并方法,并且它们具有合并队列感知功能。 生成的提交历史与从底部开始依次单独合并每个拉取请求的结果相同。

注意

如果通过 API 合并并想要使用堆叠拉取请求,则需要更新才能使用新的堆栈合并 API。 请参阅“用于拉取请求的 REST API 终结点”。

后续步骤