Git PR 工作流
自动化 PR 全流程:检测状态 → 提交 → 创建 PR → 等 CI → 修复 → 循环 → 合并。
执行原则
- 先检测状态再继续 — 从当前状态接续
- 不要停下来问用户 — 每步完成后直接继续
- 循环修复直到通过 — CI 失败 → 查错 → 修复 → 推送 → 重复
- 完整执行 — CI 通过(或确认该仓库无 CI)、Copilot 问题处理完、合并完成才算结束
状态检测
gh pr view --json number,state 2>/dev/null # 是否已有 PR
gh pr checks # CI 状态
git status # 未提交更改
| 状态 | 操作 |
|---|---|
| 无 PR | 从创建 PR 开始 |
| CI 运行中 | 等待完成 |
| CI 失败 | 查看错误日志 → 修复 → 推送 |
| CI 通过 | 检查 Copilot 评论 |
| 确认无 CI(见下) | 跳过第 4-5 步,直接进第 6 步 |
| 全绿且评论已处理 | 自动合并 |
先分清「CI 失败」和「没有 CI」:gh pr checks 在两种情况下都返回退出码 1——
有检查但失败时列出失败项;仓库没配 workflow 时输出 no checks reported on the '<branch>' branch。
后者不是失败,别拿它去 gh run view --log-failed 捞日志(也捞不到),更不能因此阻塞合并。
退出码 8 是「检查进行中」,和失败的 1 不是一回事——别把还在跑的 CI 当成挂了就去改代码。
不过 no checks reported 只说明这个 head commit 没有 check run,不等于仓库没有 CI——
也可能 workflow 存在但没配到这个分支/事件上。所以要落实一下再决定跳不跳:
[ -d .github/workflows ] && echo "有 workflow 目录,属于配置问题" || echo "确实没有 CI,可跳过第 4-5 步"
别改用 gh api repos/{owner}/{repo}/actions/workflows 的 total_count 来判断——
它把 GitHub 自己的动态 workflow 也算进去。本仓库没有任何 .github/workflows 文件,
该接口却返回 total_count: 2,两条都是 dynamic/.../copilot-pull-request-reviewer。
按它判断会得出「有 CI」的错误结论,然后无限等一个永远不会出现的 check。
(别用 ls .github/workflows/:目录不存在时它自己就非零退出并往 stderr 打错误,
在状态机里又变成一个假的「步骤失败」——正是这一步想避免的毛病。)
流程
- 检查分支 — 在 main 上则先创建新分支
- 提交更改 —
git add+git commit - 推送 + 创建 PR —
git push -u+gh pr create - 等待 CI —
gh pr checks --watch;输出no checks reported时按上面的办法确认无 CI,是则跳到第 6 步 - CI 失败时 —
gh run view <id> --log-failed→ 修复 → 推送 - Copilot 评论 — 先确认审查已被请求(见下),再拉评论:
gh pr view --comments+gh api repos/{owner}/{repo}/pulls/$PR_NUMBER/comments→ 按下表评估 → 只修必要问题 → 推送 - 循环 4-6 直到全部通过
- 自动合并 — 全部检查通过且无未处理 review →
gh pr merge --merge --delete-branch;若有 review 请求变更或未通过 → 暂停合并并通知用户
请求 Copilot 审查
别假设审查会自动触发——很多仓库不会,同一个仓库也可能时有时无(本仓库 PR #1 有、#2/#3 没有)。
先看是否已请求或已审:gh pr view <N> --json reviewRequests,reviews。没有就手动请求:
gh pr edit <N> --add-reviewer @copilot # 或建 PR 时 gh pr create --reviewer @copilot
@ 前缀是关键,跟 gh 版本无关。gh 2.73.0 实测:@copilot 退出码 0 成功;
Copilot 和 copilot(不带 @)都报 GraphQL: Could not resolve user with login 'copilot'。
gh 2.88.0 的 changelog 只是把它写进了文档并加了交互式选择,服务端此前已经认这个写法——
别因为本机 gh 旧就先入为主走兜底路径。
真要兜底(比如 @copilot 在某仓库不可用)走 API:
gh api repos/{owner}/{repo}/pulls/<N>/requested_reviewers -X POST \
-f 'reviewers[]=copilot-pull-request-reviewer[bot]'
走 API 时只有带 [bot] 后缀的 slug 能成:不带 [bot] 的裸 slug 报 422
Reviews may only be requested from collaborators。
Copilot 可能因配额用尽而审不了——此时 review 状态是 COMMENTED、正文写着
unable to review ... reached their quota limit、没有任何行内评论。这不是「审查通过」,
也不是「请求变更」。用户已定(2026-09-18):配额用完就不管——不重试、不再等、不暂停合并,
CI 通过就照常合并,最终汇报里带一句「Copilot 配额用完,这次没审」即可。
POST 返回 200 但 requested_reviewers 是空数组属正常——GitHub 立刻把请求转成进行中的审查,
这个字段随即清空。别据此判定失败又重发,以评论是否出现为准。
别给耗时写死一个数。Copilot 有 Lite / Balanced 两档 effort,Balanced 会路由到高推理模型 做更长的分析,两档的实际耗时差一个量级(本仓库 Lite 实测约 100 秒)。做有上限的轮询即可: 20 秒一轮、上限 15 次(约 5 分钟)。别只等一次 30 秒就断定「没有评论」—— 那是把还没写完的审查当成没有审查。
回复行内评论走 .../comments/<comment_id>/replies。body 里带反引号或引号时,
-f body=... 会被 shell 转义炸成 EOF 错误;写进 JSON 文件用 --input 才稳。
评估每条 Copilot 评论的必要性
不要盲目修改所有 Copilot 建议!
| 必须修改 | 可以忽略 |
|---|---|
| SQL注入、XSS、敏感信息泄露 | 过度防御的建议 |
| 实际会导致问题的 Bug | 假阳性、误报 |
| 严重影响可读性的风格问题 | 纯粹的风格偏好 |
| 明显的性能问题 | 微优化、过早优化 |
| 有实际收益的改进 | 教条式建议 |
判断标准: 当前上下文是否真有问题?修改有实际收益?符合项目需求?
输出决策:需要修改: [原因] / 忽略: [原因]