merge-open-prs
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseMerge the open PRs as one stack
将开放PR作为一个栈合并
Snapshot the open PRs. That list is the work set. Assemble it into one native
GitHub stack, resolve conflicts until the top branch is the intended post-merge
tree, then merge the whole stack with one .
gh stack mergeStanding rules:
- The work set does not grow. A PR opened after the snapshot is ignored.
After every ,
sync, andsubmit, compare stack membership to the work set; drop extras (unstack and rebuild) and never merge them.view - A default-branch move is in scope. Sync, resolve, and re-verify before merging.
- Every PR lands through the forge. Never merge into a local default branch and push, and never push straight to the default branch. Do local git work only on the PRs' own branches, in a temporary worktree you remove afterwards.
- Read the skill before any
gh-stackcommand and use its non-interactive flags.gh stack
对开放PR进行快照,该列表即为工作集合。将其组装为一个原生GitHub栈,解决冲突直至顶层分支与合并后的预期代码树一致,然后通过一条命令合并整个栈。
gh stack merge通用规则:
- 工作集合不会扩大:快照之后新开的PR将被忽略。每次执行、
sync和submit后,对比栈成员与工作集合;移除额外的PR(取消栈关联并重建)且绝不合并它们。view - 默认分支变动在处理范围内:合并前需同步、解决冲突并重新验证。
- 所有PR均通过平台合并:切勿合并到本地默认分支后推送,也切勿直接推送到默认分支。仅在PR自身的分支上进行本地Git操作,操作完成后移除临时工作区。
- 执行任何命令前,请先查看
gh stack技能文档,并使用其非交互式参数。gh-stack
1. Snapshot the work set
1. 快照工作集合
sh
gh api --paginate 'repos/{owner}/{repo}/pulls?state=open&per_page=100' \
--jq '.[] | {number,title,headRefName:.head.ref,headRefOid:.head.sha,baseRefName:.base.ref,isDraft:.draft}'Read every page. If the user named specific PRs, those are the work set;
otherwise every open PR is. Record numbers, head SHAs, and head branches.
For anything but a single obvious PR, build a file-overlap map:
sh
gh pr view <n> --json files,headRefName,headRefOid,baseRefName,isDraft,reviewDecision,statusCheckRollup,isCrossRepository,maintainerCanModify
gh pr diff <n>An unready PR (draft, requested changes, failing checks) stays in the work set.
Make it mergeable; do not drop it, and do not merge over unanswered requested
changes without user direction.
Check whether the PRs are already in a native stack:
sh
gh api graphql -f owner={owner} -f repo={repo} -f query='
query($owner:String!,$repo:String!){
repository(owner:$owner,name:$repo){
pullRequests(states:OPEN, first:100){
nodes{ number headRefName baseRefName
stack{ number entries(first:50){ nodes{ position pullRequest{ number } } } } } } } }'stacknullIf the work set is empty, stop. If it is one PR, skip to the single-PR merge in
section 6. Two or more PRs become one stack, even when files-disjoint; never
merge them individually with .
gh pr mergesh
gh api --paginate 'repos/{owner}/{repo}/pulls?state=open&per_page=100' \
--jq '.[] | {number,title,headRefName:.head.ref,headRefOid:.head.sha,baseRefName:.base.ref,isDraft:.draft}'读取每一页内容。如果用户指定了特定PR,则这些PR为工作集合;否则所有开放PR均为工作集合。记录PR编号、头部SHA值和头部分支。
除单个明确的PR外,需构建文件重叠映射:
sh
gh pr view <n> --json files,headRefName,headRefOid,baseRefName,isDraft,reviewDecision,statusCheckRollup,isCrossRepository,maintainerCanModify
gh pr diff <n>未就绪的PR(草稿、有待修改、检查未通过)仍保留在工作集合中。需使其可合并;不得丢弃,且未经用户指示不得合并存在未处理修改请求的PR。
检查PR是否已处于原生栈中:
sh
gh api graphql -f owner={owner} -f repo={repo} -f query='
query($owner:String!,$repo:String!){
repository(owner:$owner,name:$repo){
pullRequests(states:OPEN, first:100){
nodes{ number headRefName baseRefName
stack{ number entries(first:50){ nodes{ position pullRequest{ number } } } } } } } }'即使PR通过基础分支链式关联,未入栈的PR的字段为。
stacknull如果工作集合为空,则停止操作。如果只有一个PR,跳至第6节的单个PR合并流程。两个或多个PR需合并为一个栈,即使文件无重叠;切勿使用单独合并它们。
gh pr merge2. Choose the stack order
2. 选择栈顺序
Files-disjoint PRs cannot conflict textually in any order, so order for
semantics and verifiability. In priority order:
- Small, isolated PRs at the bottom (config tweaks, dependency bumps, tooling that helps verify the layers above).
- Foundational before dependent: when one PR calls what another adds, the dependency sits lower.
- Shared-state PRs at the top: a version constant, migration number, or checked-in generated artifact compounds with everything below.
- Otherwise by blast radius, smallest at the bottom.
An existing base chain is evidence for that order. A user-stated order wins.
State the order and a one-line reason per layer before you build.
文件无重叠的PR在任何顺序下都不会产生文本冲突,因此需按语义和可验证性排序。优先级顺序如下:
- 小型、独立的PR置于栈底(配置调整、依赖版本更新、可帮助验证上层代码的工具类PR)。
- 基础PR优先于依赖PR:当一个PR调用另一个PR新增的内容时,被依赖的PR置于下层。
- 涉及共享状态的PR置于栈顶:版本常量、迁移编号或已提交的生成产物会与下层所有代码产生关联。
- 否则按影响范围排序,影响范围最小的置于栈底。
现有的基础分支链式关联可作为排序依据。用户指定的优先级优先于上述规则。构建栈之前,需说明排序顺序及每层的一行理由。
3. Know the gate
3. 了解合并限制
sh
gh repo view --json mergeCommitAllowed,squashMergeAllowed,rebaseMergeAllowed
gh api repos/{owner}/{repo}/branches/{branch}/protection # may 404 even when gated
gh api repos/{owner}/{repo}/rulesetsPass the repo's merge method explicitly on . Rulesets and
classic protection are separate; check both for required checks, required
reviews, and strict up-to-date policy. cannot bypass any of
them.
gh stack mergegh stack mergesh
gh repo view --json mergeCommitAllowed,squashMergeAllowed,rebaseMergeAllowed
gh api repos/{owner}/{repo}/branches/{branch}/protection # 即使存在限制也可能返回404
gh api repos/{owner}/{repo}/rulesets在执行时需明确传递仓库的合并方式。规则集与传统保护机制相互独立;需检查两者的必填检查项、必填评审要求和严格的最新状态策略。无法绕过任何限制。
gh stack mergegh stack merge4. Assemble one native stack
4. 组装原生栈
A native stack requires one repository (no fork PRs), stacked PRs enabled
( and exit 9 otherwise), and permission to rewrite the branches:
building a chain from PRs that each target the default branch rebases and
force-pushes every branch above the bottom. Get explicit approval before
rewriting a branch you do not own, and disclose every rewrite. If any condition
fails, use .
submitlinkreferences/fallback-collapse.mdIf GitHub already records exactly the planned stack, do not rebuild:
sh
gh stack checkout <anyWorkSetPR> # gh stack unstack --local first if a local stack overlaps
gh stack view --jsonIf the PRs already chain by base in the planned order and is null,
registers them without rewriting.
stackgh stack link <bottomPR> <nextPR> <topPR>Otherwise rebuild. only appends and never removes, so unstack any
grouping that overlaps, then:
linksh
git fetch origin原生栈需要满足以下条件:单个仓库(无分叉PR)、已启用栈式PR(否则和命令会返回错误码9)、拥有分支重写权限:将每个以默认分支为目标的PR组装为链式结构时,会对栈底上方的所有分支执行变基和强制推送。在重写非自己拥有的分支前需获得明确批准,并告知所有重写操作。如果任何条件不满足,请使用中的方案。
submitlinkreferences/fallback-collapse.md如果GitHub已记录与计划完全一致的栈,则无需重建:
sh
gh stack checkout <anyWorkSetPR> # 如果本地栈存在重叠,先执行gh stack unstack --local
gh stack view --json如果PR已按计划顺序通过基础分支链式关联,且字段为,则执行命令将它们注册为栈,无需重写分支。
stacknullgh stack link <bottomPR> <nextPR> <topPR>否则进行重建。命令仅能追加PR,无法移除,因此需取消任何重叠的栈分组,然后执行:
linksh
git fetch origininit CREATES a missing local branch from the one below, silently producing an
init命令会从下层分支创建缺失的本地分支,可能会生成空层。需先将分支实例化:
empty layer. Materialize them first:
—
for b in <bottomBranch> <nextBranch> <topBranch>; do
git show-ref --verify --quiet "refs/heads/$b" || git branch "$b" "origin/$b"
done
gh stack init --base <default-branch> <bottomBranch> <nextBranch> <topBranch>
gh stack rebase # exit 3: resolve, git add, gh stack rebase --continue
gh stack submit --auto
gh stack view --json # membership and order must match the work set
undefinedfor b in <bottomBranch> <nextBranch> <topBranch>; do
git show-ref --verify --quiet "refs/heads/$b" || git branch "$b" "origin/$b"
done
gh stack init --base <default-branch> <bottomBranch> <nextBranch> <topBranch>
gh stack rebase # 返回错误码3:解决冲突,执行git add,然后gh stack rebase --continue
gh stack submit --auto
gh stack view --json # 成员和顺序必须与工作集合匹配
undefined5. Keep the stack current, resolve, verify
5. 保持栈同步、解决冲突、验证
Record the default-branch tip after every fetch. When it moves, or any layer
reports :
needsRebasesh
gh stack syncsyncgh stack rebaseSync abortedsyncIf a teammate pushes to a work-set branch or closes a work-set PR, stop and
ask. If someone merges a work-set PR to the default branch, that is a trunk
move: sync and continue.
Fix a layer's conflict on that layer, then ; do not
dump fixes onto the top branch. covers textual
resolution, lockfiles, and the semantic conflicts Git cannot see (version
bumps, migration numbers, combined-tree breaks). Before pushing a fix, confirm
and match the remote you will update.
gh stack rebase --upstackreferences/conflicts.mdisCrossRepositorymaintainerCanModifyVerify with the repo's own checks:
- Baseline the default branch in the worktree so failures are attributable.
- On the top branch (the post-merge tree): build, format, lint, and run the tests for the stack's blast radius.
- Let each PR's required checks finish; they still gate .
gh stack merge - After the merge, run the full suite on the actual default branch and confirm integration tests ran rather than skipped.
Re-verify after every successful sync, and immediately before the merge.
每次拉取后记录默认分支的最新提交。当默认分支变动,或任何一层PR显示时:
needsRebasesh
gh stack syncsyncgh stack rebaseSync abortedsync如果队友推送到工作集合中的分支,或关闭了工作集合中的PR,请停止操作并询问用户。如果有人将工作集合中的PR合并到默认分支,这属于主干变动:同步后继续操作。
在对应分支上解决该层的冲突,然后执行;切勿将修复内容全部放到顶层分支。涵盖文本冲突解决、锁文件以及Git无法识别的语义冲突(版本更新、迁移编号、合并代码树断裂)。推送修复前,请确认和与你要更新的远程仓库匹配。
gh stack rebase --upstackreferences/conflicts.mdisCrossRepositorymaintainerCanModify使用仓库自身的检查项进行验证:
- 在工作区中以默认分支为基准,以便将故障归因于具体PR。
- 在顶层分支(合并后的代码树)上:构建、格式化、代码检查,并针对栈的影响范围运行测试。
- 等待每个PR的必填检查完成;它们仍会限制命令的执行。
gh stack merge - 合并后,在实际的默认分支上运行完整测试套件,并确认集成测试已运行而非跳过。
每次成功同步后以及合并前需重新验证。
6. Merge once
6. 一次性合并
Re-read and the default-branch tip. Membership must
equal the work set and no head may have moved since verification.
gh stack view --jsonsh
gh stack merge <stack-number> --yes <verified-method-flag>All-or-nothing: if any PR cannot merge, none do. Drafts block;
first, with user direction where the draft was deliberate. A merge queue queues
the stack instead and picks its own method; watch the PRs land. Afterwards
and remove the worktree.
gh pr readygh stack sync --pruneSingle PR:
sh
gh pr view <n> --json headRefOid
gh pr merge <n> <verified-method-flag> --delete-branch --match-head-commit <sha>--admin重新查看的输出和默认分支的最新提交。成员必须与工作集合一致,且自验证以来头部提交不得变动。
gh stack view --jsonsh
gh stack merge <stack-number> --yes <verified-method-flag>全有或全无:如果任何PR无法合并,则所有PR都不会合并。草稿PR会阻止合并;需先执行,若草稿状态是用户故意设置的,需先获得用户指示。合并队列会将栈加入队列并选择自己的合并方式;需关注PR的合并状态。之后执行并移除工作区。
gh pr readygh stack sync --prune单个PR的合并命令:
sh
gh pr view <n> --json headRefOid
gh pr merge <n> <verified-method-flag> --delete-branch --match-head-commit <sha>仅在获得明确批准的情况下使用参数,并在报告中说明。
--admin7. Report
7. 生成报告
- Work-set PRs, PRs ignored as later arrivals, and whether files overlapped.
- Stack number and layers bottom to top with a reason each; found or built. Any work-set PR not merged, and why.
- Conflicts resolved, branches rewritten, PRs folded, any bypass.
- Default-branch moves and what you did about them.
- What you ran and what passed, including on the final default branch.
- Final default-branch SHA and remaining open PRs.
If the request chains a release, use after CI is green on the
merged commit.
$tag-release- 工作集合中的PR、因晚于快照而被忽略的PR,以及文件是否存在重叠。
- 栈编号和从底到顶的各层PR及对应的理由;栈是已存在还是新建的。未合并的工作集合PR及原因。
- 解决的冲突、重写的分支、合并的PR、任何绕过操作。
- 默认分支的变动及对应的处理措施。
- 运行的检查项及结果,包括最终默认分支上的检查。
- 最终默认分支的SHA值和剩余的开放PR。
如果请求包含发布流程,请在合并提交的CI检查通过后使用。
$tag-release