
使用 gh stack 在 PostHog 仓库管理 GitHub 原生 Stacked PR从分层、发布、同步到合并的完整工作流【免费下载链接】posthog:hedgehog: PostHog is the leading platform for building self-driving products. Our developer tools – AI observability, analytics, session replay, flags, experiments, error tracking, logs, and more – capture all the context agents need to diagnose problems, uncover opportunities, and ship fixes. Steer it all from Slack, web, desktop, or the MCP.项目地址: https://gitcode.com/GitHub_Trending/po/posthogStacked PR堆栈式拉取请求是把一次大型改动拆成有序的多层 PR 链的协作方式每一层 PR 的目标分支是它下一层的分支最底层指向master。本文以 PostHog 开源仓库GitHub_Trending/po/posthog为背景完整讲解如何使用 GitHub 官方gh stackCLI 创建、发布、迭代同步并最终通过 Trunk 合并队列落地一个堆栈同时覆盖云任务沙箱环境的替代路径、常见冲突处理与已知限制帮助你在该仓库中安全高效地管理多层 PR。什么是 GitHub 原生 Stacked PR以及 PostHog 仓库的约定GitHub 的原生 Stacked PR 功能已在该仓库启用。一个**堆栈stack是一条有序的 PR 链其中每个 PR 的目标base分支是它下方 PR 的分支最底层 PR 的目标是master。与手工维护多条互相 rebase 的分支相比原生堆栈把这条链当作一级对象first-class object**来跟踪PR 界面会显示整条链的栈地图stack map每一层之间的关系一目了然分支保护code owner 审批、必需检查等会应用到每一层包括中间层而不是只约束最底层在masterPR 上运行的 CI 同样会在每一层上运行。动手切分前先读 things already tried原文要求在把一个改动切分成多层之前先阅读 docs/internal/ci-things-already-tried.md。该文件记录了把两个紧密耦合的层拆成两个 Stacked PR这一尝试的结论rejected2026 年 8 月PR #87643这两层作为两个故事读起来很好但作为两个 diff 却行不通。两层修改了相同的四个模块有时甚至是相同的行上层删除了下层修正的一个代码块还改变了一个下层拆分出的函数的签名导致下层每一次修正都要在这些冲突中重来一遍而且每次 restack 都要重复。它给出的原则值得记住按 diff 面diff surface切分改动而不是按故事story切分。如果两层会改动相同的行一个 PR 的评审成本反而低于两个 PR。同时AGENTS.md 的 Stacked PRs 一节也明确仓库已启用 GitHub 原生 Stacked PR应使用gh stackCLI 与本技能/stacking-prs来管理分支链而不要手工维护。环境准备安装 gh-stack 扩展本技能针对gh-stackv0.1.0编写。安装 GitHub 官方扩展gh extension install github/gh-stack # 首次安装 # 已安装过时版本时升级 gh extension upgrade stackGitHub 官方文档将 Stacked PR 拆为两部分参考关于 Stacked PR 的概念说明about stacked PRs与 Stacked PR 的 CLI 命令参考Stacked PRs CLI commands。命令细节以你安装的版本为准官方文档同样值得在遇到某件事做不了时先查阅再下结论。云任务沙箱用 gh_stack 代替 gh stack本技能其余部分假设你在开发者机器上操作。云任务cloud task运行环境会阻断git commit与git push因为未签名提交不能离开沙箱——这会让所有发布堆栈的gh stack命令submit、sync、push以及带分支参数的link失效而gh stack add -m会执行 commit同样不可用。在沙箱中正确的做法是用签名提交工具构建堆栈再用gh_stackMCP 工具把各层链接起来。gh_stack驱动 GitHub 的 Stacks REST API从不执行 push用git_signed_commit提交每一层并传入一个新的branch——当前 checkout 已经位于下一层分支上所以新分支自然从那里开始用gh pr create --base 下一层分支名为每一层打开 PR用gh_stack操作create按从底到顶顺序传入pull_requests把它们链接成堆栈。重新堆叠restack某层时先 checkout 那一层执行git rebase 其父分支再用git_signed_rewrite重新发布onto参数传父分支名。注意两点gh stack rebase可以自己完成 rebase但没有任何命令可以把结果发布出去——gh stack push和gh stack sync都会 push在沙箱里不可用git_signed_rewrite会把本地 HEAD 指向的内容原样重放branch参数只用于决定哪个远端引用被移动。因此被重写的必须是当前 checkout 的分支否则会把错误的历史发布到该分支上。创建堆栈在开发者机器上创建堆栈的三个核心命令gh stack init my-feature-db # 最底层分支基于 master # ...提交代码... gh stack add my-feature-api # 下一层基于前一个分支 # ...提交代码... gh stack add -Am add UI my-feature-ui # 一步完成暂存全部改动并提交-A等价于git add -A暂存所有改动-m指定提交信息两者可组合为-Am。收养已有分支或 PR收养本地已有分支按从底到顶的顺序gh stack init branch1 branch2 branch3链接 GitHub 上已存在、本地没有跟踪的 PRgh stack link pr pr pr同样从底到顶分支名与 PR URL 也可以传入。如果先传一个堆栈编号则把后续 PR追加到该堆栈gh stack link stack pr。分层原则按可评审单元切分例如 migration / backend / frontend或 mechanical-rename / behavior-change。每一层 PR 都必须能独立评审、独立合并保持堆栈浅2–4 层为宜。每一层都会成倍放大 CI 成本与 rebase 折腾而且深堆栈的一次性推送可能触发 GitHub 的dispatch 上限详见 AGENTS.md Stacked PRs 一节500 次 workflow run / 10 秒超出后以startup_failure失败还会拖垮同一时间窗口内的无关运行。发布堆栈gh stack submit --auto该命令会推送所有分支、为每个 PR 创建正确的 base并在 GitHub 上把整条链链接成堆栈。--auto会把新建 PR默认创建为 draft草稿这正是本仓库的推荐默认值——draft 只运行收窄后的 CI 矩阵可以省下 runner 积分用gh pr ready n逐层把 PR 标记为 ready或者加--open一次把全部层标记为 ready不带任何标志运行gh stack submit会进入交互式编辑器为每层填写标题和描述。注意该编辑器中新建 PR默认是 ready-for-review状态如果想要 draft需要手动切换 CREATE AS 开关。每一层都是一个普通 PR需要conventional-commit 格式的标题描述则按 .github/pull_request_template.md 填写。模板还明确鼓励堆栈而非硬塞当 diff 里包含两个或更多可分离的步骤migration 之后接 behavior、rename 之后接 rewrite时应该开一个堆栈而不是一个巨型 PR。迭代与保持同步gh stack sync # fetch、级联 rebase 到 master 与各父分支、force-with-lease 推送、同步 PR 状态 gh stack sync --prune # 额外删除已合并 PR 对应的本地分支修复中间层与冲突处理修复堆栈中间的某一层先 checkout 到该分支gh stack down/gh stack switch提交代码再gh stack sync。也可以gh stack rebase --upstack只 rebase 你之上的层或加--no-trunk跳过拉取 masterrebase 冲突gh stack sync在冲突时会原样恢复所有分支不留下半成品状态此时运行gh stack rebase解决冲突后用gh stack rebase --continue继续或--abort放弃。状态查看与结构调整gh stack view --short显示各层状态--json便于脚本处理某层出现⚠表示它需要 rebase这会阻塞合并gh stack checkout stack-number|PR|URL可以拉取并跟踪一个你本地没有的堆栈包括同事的堆栈gh stack modify以交互方式对层进行重排、折叠、删除或重命名gh stack unstack移除 GitHub 上的堆栈--local只删除本地跟踪。关键纪律批量工作后再 sync。每次 sync 都会 force-push 并对每个被 rebase 的层重跑完整 CI 矩阵所以应该在你确实需要 rebase 时才 sync而不是为了跟踪 master 而频繁 sync分支可能自己移动ReviewHog 等机器人会把修复提交直接推到 PR 分支上。gh stack sync会先 fetch 再以--force-with-lease推送因此当分支被移动过时会拒绝推送——把这种拒绝理解为有人在这里提交了去看一下而不是重试在对某层做任何手动git push或 rebase 之前先git fetch origin并 fast-forward 到远端头绝不对层分支做裸 force-pushci:preflightpre-push 钩子会和普通推送一样运行绝不绕过它--no-verify。它通过hogli ci:preflight --strict阻止确定性 CI 破坏lint、lockfile、migration 冲突被推上去。合并堆栈两条合并路径都必须经过 Trunk 合并队列通过/merging-prs绝不使用gh stack merge。此外根据 AGENTS.md Merging PRs 一节的硬性要求Agent 在将识别出的堆栈入队enqueue、重新入队或以任何方式让某一层落地之前必须先获得用户在当前会话中的明确批准——不能从准备好 PR把它推向合并标记 ready解决 blocker等请求中推断批准。路径一整栈一次合并默认Trunk 合并队列原生支持堆栈把一个 PR 入队会把它以及下方每一个未合并的层一起入队整体测试、原子合并。获得用户明确批准后在最顶层PR 上评论/trunk merge落地整个堆栈如果只想落地底部的一部分则在最上方的准备就绪层上评论。每一层在合并前都必须单独通过/merging-prs的 preflightready、已批准、无失败检查——pending 检查没关系队列会等它中间层处于 draft 或缺少批准会阻塞其上方的所有层。路径二自底向上、逐层合并获得用户明确批准后对基于master的最底层执行/merging-prs与合并普通 PR 完全相同。合并后GitHub 会自动把下一层 retarget 到master并更新堆栈。合并之后gh stack sync --prune # 把剩余层重放到 squash 后的提交上删除已合并分支为什么绝不使用 gh stack mergegh stack merge会绕过合并队列、把整条链直接通过 GitHub API 合并导致最底层在 AGENTS.md 要求的路径之外到达master而且合并任意一层会连带合并它下方所有未合并的层所以只有在这些层都已评审通过、检查全绿时中间层合并才是安全的。其他要点每一层的门禁独立的 approving review、code owner review、required checks 与签名提交signed commits各自生效堆栈不支持 rule bypass 与 auto-merge所以--auto在这里帮不上忙队列期间禁止操作某一层在合并队列中时绝不执行gh stack sync、rebase或push——force-push 会把它踢出队列。gh stack push知道跳过GitHub合并队列中的分支但它看不到 Trunk 的队列。脚本化与自动化列出所有堆栈gh api repos/{owner}/{repo}/stacks查看单个堆栈.../stacks/stack-number。堆栈编号与 PR 编号共用同一个序列因此永远不会冲突本地堆栈状态gh stack view --json适合在 CI 脚本或自动化工具中解析。已知限制当前实现preview 阶段存在以下约束所有分支必须位于同一个仓库内不支持跨 fork 的堆栈链必须是严格线性的不允许分支结构每一层在合并前都需要先 rebaseGitHub Desktop 完全不支持堆栈。这些都是 preview 时代的限制在断定某件事做不了之前建议先查阅上文提到的 GitHub 官方 Stacked PR 文档与 CLI 命令参考。仓库内的延伸阅读AGENTS.mdStacked PRs含 dispatch 上限、restack 纪律、merge queue guard与Merging PRs/trunk merge、/trunk cancel、明确批准要求两节是本技能的总纲.agents/skills/merging-prs/SKILL.md/trunk merge的 preflight、入队、监控与失败处理完整流程其中明确说明入队一个堆栈 PR 即入队其下方所有未合并层docs/internal/ci-things-already-tried.md记录了按故事而非按 diff 面切分堆栈被否决的实证PR #87643是动手切层前必读的教训档案.github/pull_request_template.md每一层 PR 的标题与描述规范以及diff 含多个可分离步骤时开堆栈而非硬塞一个 PR的约定。【免费下载链接】posthog:hedgehog: PostHog is the leading platform for building self-driving products. Our developer tools – AI observability, analytics, session replay, flags, experiments, error tracking, logs, and more – capture all the context agents need to diagnose problems, uncover opportunities, and ship fixes. Steer it all from Slack, web, desktop, or the MCP.项目地址: https://gitcode.com/GitHub_Trending/po/posthog创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考