push-pr

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Push & PR

Push & PR

Push commits and create/update pull requests with automatic branch management and scope-aware multi-PR splitting.
推送提交记录(commit)并创建/更新拉取请求(PR),支持自动分支管理和基于范围的多PR拆分。

Arguments

参数

Parse flexibly from
$ARGUMENTS
:
  • status:
    1
    =opened,
    2
    =draft,
    3
    =ready (default: new PR=opened, update=draft)
  • base-branch: Target branch (default:
    main
    )
$ARGUMENTS
中灵活解析:
  • status
    1
    =已开启,
    2
    =草稿,
    3
    =就绪(默认:新建PR为已开启,更新PR为草稿)
  • base-branch:目标分支(默认:
    main

Pre-Flight Context

预执行上下文

Injected at invocation — analyze before taking any action:
  • Working tree status:
    !git status --porcelain
  • Current branch:
    !git rev-parse --abbrev-ref HEAD
  • Unpushed commits:
    !git rev-list @{u}..HEAD --count 2>/dev/null || echo "no upstream"
  • Recent commits:
    !git log origin/main..HEAD --oneline 2>/dev/null
    (assumes main base; see Step 3 if base differs)
  • Diff stat:
    !git diff origin/main...HEAD --stat 2>/dev/null
    (captured before fetch; re-run if stale)
调用时注入——执行任何操作前先分析:
  • 工作区状态:
    !git status --porcelain
  • 当前分支:
    !git rev-parse --abbrev-ref HEAD
  • 未推送的提交记录:
    !git rev-list @{u}..HEAD --count 2>/dev/null || echo "no upstream"
  • 近期提交记录:
    !git log origin/main..HEAD --oneline 2>/dev/null
    (假设基准分支为main;若基准分支不同,请查看步骤3)
  • 差异统计:
    !git diff origin/main...HEAD --stat 2>/dev/null
    (获取前捕获;若过时则重新运行)

Workflow

工作流程

1. Pre-Flight

1. 预执行检查

Run
git fetch origin
to sync remote state.
If the working tree status above shows uncommitted changes, invoke
Skill: commit
to commit first.
Complete when: remote is fetched and working tree is clean.
运行
git fetch origin
同步远程仓库状态。
如果上述工作区状态显示存在未提交的更改,先调用
Skill: commit
完成提交。
完成标志:远程仓库已同步,工作区状态干净。

2. Branch Management

2. 分支管理

If on main/master with unpushed commits, cut a feature branch before proceeding.
Branch naming: prefix from the primary commit's conventional type (
feat/
,
fix/
,
docs/
,
chore/
,
refactor/
); slug from the commit scope or subject, lowercase hyphens only, max 45 chars total (keeps branch names readable in GitHub's UI and avoids truncation in terminal prompts). Use the scope if present (
feat(auth)
feat/auth
); otherwise condense the subject to 2–4 words (
fix login redirect timeout
fix/login-redirect
).
bash
git checkout -b <derived-branch-name>
git branch -f main origin/main
git branch -f
moves main's pointer back to origin/main without checkout or
--hard
— non-destructive and never triggers permission denials.
If already on a feature branch: skip to step 3.
Complete when: HEAD is on a feature branch (not main/master).
如果当前处于main/master分支且存在未推送的提交记录,先创建功能分支再继续操作。
分支命名规则:以主要提交记录的约定类型作为前缀(
feat/
fix/
docs/
chore/
refactor/
);以提交记录的范围或主题作为后缀,仅使用小写连字符,总长度不超过45个字符(确保分支名称在GitHub界面中可读,避免在终端提示中被截断)。如果存在范围(如
feat(auth)
feat/auth
)则使用范围;否则将主题浓缩为2-4个单词(如
fix login redirect timeout
fix/login-redirect
)。
bash
git checkout -b <derived-branch-name>
git branch -f main origin/main
git branch -f
将main分支的指针移回origin/main,无需切换分支或使用
--hard
参数——无破坏性且不会触发权限拒绝。
如果已处于功能分支:跳至步骤3。
完成标志:当前HEAD指向功能分支(而非main/master)。

3. Context Gathering

3. 上下文收集

Derive working variables from pre-flight context and arguments:
  • BASE
    = base-branch argument, or
    main
    if not provided
  • BRANCH
    = current branch name (from pre-flight injection)
Use the pre-flight context injected above. If the base branch differs from
main
, re-gather against
origin/$BASE
:
bash
git log origin/$BASE..HEAD --oneline --reverse
git diff origin/$BASE...HEAD --stat
Always compare against
origin/$BASE
, not local
$BASE
— the PR targets the remote branch, so comparisons must match what GitHub will see.
Record: commit count, conventional-commit types and scopes present, total diff lines (approximate from
--stat
output).
Complete when: commit count, scope/type inventory, and approximate diff size are known.
从预执行上下文和参数中推导工作变量:
  • BASE
    = 传入的base-branch参数,若未提供则为
    main
  • BRANCH
    = 当前分支名称(来自预执行上下文注入)
使用上述注入的预执行上下文。如果基准分支与
main
不同,针对
origin/$BASE
重新收集信息:
bash
git log origin/$BASE..HEAD --oneline --reverse
git diff origin/$BASE...HEAD --stat
始终与
origin/$BASE
对比,而非本地
$BASE
——PR的目标是远程分支,因此对比结果必须与GitHub将看到的内容一致。
记录:提交记录数量、存在的约定式提交类型和范围、差异总行数(从
--stat
输出估算)。
完成标志:已获取提交记录数量、范围/类型清单以及大致差异规模。

4. Scope Analysis

4. 范围分析

Evaluate whether the changeset warrants multiple PRs. A split is warranted when either:
  • Size: total diff exceeds ~400 lines (code lines; ignore lock files and generated files) — beyond this threshold, reviewer fatigue degrades review quality and catch rate
  • Diversity: commits span 3+ distinct conventional-commit scopes or types (e.g.,
    feat(auth)
    ,
    fix(ui)
    ,
    chore(deps)
    ) — multiple scopes mean the changeset lacks a single narrative, making review harder and revert riskier
If neither condition is met: proceed to step 5 as a single PR.
If either condition is met — propose stacked PRs:
Cluster commits by scope/type in the order they were made. Each cluster becomes one PR targeting the previous cluster's branch (the first targets
$BASE
). Present the plan:
Proposed stacked PRs (each PR targets the previous branch):
  PR 1  [base: main]         feat/auth          — commits: abc1234, def5678
  PR 2  [base: feat/auth]    fix/ui-redirect    — commits: ghi9012
  PR 3  [base: fix/ui-...]   chore/cleanup      — commits: jkl3456
Use AskUserQuestion: "Split into N stacked PRs as shown above, or push as a single PR?"
If user declines split: proceed to step 5 as a single PR.
If user confirms split — stacked PR execution:
For each cluster in order:
  1. Create a branch from the previous cluster's branch (
    $BASE
    for cluster 1):
    bash
    git checkout -b <cluster-branch> <previous-branch>
    git cherry-pick <sha1> <sha2> ...
  2. Push:
    git push -u origin <cluster-branch>
  3. Generate PR body using the format script with
    --base <previous-branch>
    :
    bash
    python3 ${CLAUDE_PLUGIN_ROOT}/skills/push-pr/scripts/format-pr-body.py --base "<previous-branch>"
  4. Create PR targeting the correct base branch.
  5. Repeat for next cluster.
After all PRs are created, check out the last cluster's branch and report the full stack (see Output). Exit — skip steps 5–7.
Complete when: user has chosen single-PR or stacked, and stacked flow is finished if chosen.
评估变更集是否需要拆分为多个PR。满足以下任一条件时应拆分:
  • 规模:总差异超过约400行(代码行;忽略锁文件和生成文件)——超过此阈值后,审核者疲劳会降低审核质量和问题检出率
  • 多样性:提交记录涵盖3个及以上不同的约定式提交范围或类型(如
    feat(auth)
    fix(ui)
    chore(deps)
    )——多个范围意味着变更集缺乏统一的叙事逻辑,会增加审核难度和回滚风险
如果两个条件都不满足:继续步骤5,创建单个PR。
如果满足任一条件——建议创建堆叠式PR:
按提交顺序将提交记录按范围/类型分组。每个分组成为一个PR,目标分支为上一个分组的分支(第一个分组的目标为
$BASE
)。展示计划:
建议的堆叠式PR(每个PR以上一个分支为目标):
  PR 1  [基准: main]         feat/auth          — 提交记录: abc1234, def5678
  PR 2  [基准: feat/auth]    fix/ui-redirect    — 提交记录: ghi9012
  PR 3  [基准: fix/ui-...]   chore/cleanup      — 提交记录: jkl3456
使用AskUserQuestion:“按上述方式拆分为N个堆叠式PR,还是作为单个PR推送?”
如果用户拒绝拆分:继续步骤5,创建单个PR。
如果用户确认拆分——执行堆叠式PR流程:
按顺序处理每个分组:
  1. 基于上一个分组的分支创建新分支(第一个分组基于
    $BASE
    ):
    bash
    git checkout -b <cluster-branch> <previous-branch>
    git cherry-pick <sha1> <sha2> ...
  2. 推送:
    git push -u origin <cluster-branch>
  3. 使用格式化脚本生成PR正文,指定
    --base <previous-branch>
    bash
    python3 ${CLAUDE_PLUGIN_ROOT}/skills/push-pr/scripts/format-pr-body.py --base "<previous-branch>"
  4. 创建PR,目标为正确的基准分支。
  5. 重复上述步骤处理下一个分组。
所有PR创建完成后,切换到最后一个分组的分支并报告完整的堆叠结构(见输出部分)。退出流程——跳过步骤5-7。
完成标志:用户已选择创建单个PR或堆叠式PR;若选择堆叠式PR则已完成全部流程。

5. PR Status

5. PR状态检查

Check for an existing PR on this branch:
gh pr list --head "$BRANCH" --json number,state
Use the provided status argument, or default: new PR=opened, update=draft.
Complete when: existing PR state is known and target status is determined.
检查当前分支是否已有PR:
gh pr list --head "$BRANCH" --json number,state
使用传入的status参数,或采用默认值:新建PR为已开启,更新PR为草稿。
完成标志:已了解现有PR状态并确定目标状态。

6. Push

6. 推送代码

Always push with
git push -u origin "$BRANCH"
— the
-u
flag sets tracking on new branches and is a no-op when the upstream is already correctly set, so it is always safe to use.
If push fails because the remote branch has diverged, run
git pull --rebase origin $BRANCH
and retry the push once. If the rebase itself has conflicts, stop and report.
Complete when: branch is pushed and tracking the remote.
始终使用
git push -u origin "$BRANCH"
推送——
-u
标志会为新分支设置跟踪,对于已正确设置上游的分支则无操作,因此始终安全可用。
如果推送失败是因为远程分支已偏离,运行
git pull --rebase origin $BRANCH
并重试一次推送。如果变基过程中出现冲突,停止操作并报告。
完成标志:分支已推送并跟踪远程分支。

7. PR Creation/Update

7. 创建/更新PR

Generate the PR body using the format script:
bash
python3 ${CLAUDE_PLUGIN_ROOT}/skills/push-pr/scripts/format-pr-body.py --base "origin/$BASE"
Exit 1 means no changes found relative to base; report to user. On success, use stdout as the PR body directly.
New PR:
bash
gh pr create --title "<title>" --body "<format-pr-body output>" --base "$BASE"
使用格式化脚本生成PR正文:
bash
python3 ${CLAUDE_PLUGIN_ROOT}/skills/push-pr/scripts/format-pr-body.py --base "origin/$BASE"
返回值1表示相对于基准分支未发现变更;向用户报告此情况。执行成功时,将标准输出直接作为PR正文。
新建PR:
bash
gh pr create --title "<title>" --body "<format-pr-body output>" --base "$BASE"

If status=ready: gh pr ready

如果status=ready: gh pr ready


**Existing PR:** Add a comment listing new commits since last push; update PR status if
the status argument changed.

```bash
PR_NUM=$(gh pr list --head "$BRANCH" --json number -q '.[0].number')
gh pr comment $PR_NUM --body "New commits: ..."
Complete when: PR URL is obtained and status matches the target.

**现有PR:** 添加评论列出上次推送以来的新提交记录;如果status参数有变化,则更新PR状态。

```bash
PR_NUM=$(gh pr list --head "$BRANCH" --json number -q '.[0].number')
gh pr comment $PR_NUM --body "New commits: ..."
完成标志:已获取PR URL且状态符合目标要求。

Constraints

约束条件

Produce clean, unattributed PRs that match the project's existing commit and PR style:
  • No Co-authored-by or AI signatures — PRs should look like human-authored work
  • No "Generated with Claude Code" — same reason; attribution is the user's choice
  • No emojis in PR title or description — most project conventions use plain text
  • Use existing git user config only — never modify
    user.name
    or
    user.email
生成简洁、无归属信息的PR,匹配项目现有的提交记录和PR风格:
  • 不添加Co-authored-by或AI签名——PR应看起来像是人工编写的成果
  • 不添加"Generated with Claude Code"——原因同上;是否归属由用户决定
  • PR标题和描述中不使用表情符号——大多数项目约定使用纯文本
  • 仅使用现有的git用户配置——绝不修改
    user.name
    user.email

Edge Cases

边缘情况

  • No remote → suggest
    git remote add origin <url>
    and stop
  • No
    gh
    CLI → report requirement and stop
  • Branch behind remote → pull/rebase before pushing
  • No commits to push → report and stop
  • Cherry-pick conflict during stacked flow → stop, report the cluster name, failing commit SHA, and conflicting file(s). Suggest
    git cherry-pick --abort
    followed by manual resolution, then re-running
  • 无远程仓库 → 建议
    git remote add origin <url>
    并停止操作
  • gh
    CLI → 报告此要求并停止操作
  • 分支落后于远程 → 先拉取/变基再推送
  • 无提交记录可推送 → 报告并停止操作
  • 堆叠流程中cherry-pick冲突 → 停止操作,报告分组名称、失败的提交记录SHA和冲突文件。建议运行
    git cherry-pick --abort
    后手动解决冲突,然后重新执行流程

Output

输出

Single PR: branch name, PR URL, PR status (opened/draft/ready).
Stacked PRs: ordered list showing each PR URL and the branch it targets, plus the name of the final branch now checked out.
单个PR:分支名称、PR URL、PR状态(已开启/草稿/就绪)。
堆叠式PR:有序列表显示每个PR的URL及其目标分支,以及当前已切换到的最后一个分支的名称。