AI 写 PR 描述——从 diff 到能审

把 git diff 变成 reviewer 真愿意打开看的 PR 描述,prompt 不会编出根本不存在的 test plan。

这篇讲什么

用 AI 编程工具——Claude Code、Cursor 或 Codex——把一条做完的分支变成”reviewer 真愿意打开看”的 PR 描述的可靠流程。痛点:AI 生成的 PR 多半要么是三条 feat: did the thing 模板废话、要么编一份”描述根本不存在的测试”的 test plan。这篇讲 prompt 结构、复核 pass、就地编辑的习惯,最终产出比手写还合 reviewer 胃口的 PR 描述。

核心概念:

  • Diff 限定:只喂对 merge base 的 diff,别喂整个仓库。
  • 结构化正文:Summary / Why / Test plan / Risks——每次同样四节。
  • 复核 pass:第二个 prompt 拿 test plan 对真实测试文件查一遍。

这篇适合谁看

一天提一个以上 PR、尤其团队 review SLA 重要的工程师。或者反复退回 PR、说”这到底改了啥?“的资深 reviewer——结构化的 AI PR 描述从源头修这个问题。团队已经在做AI pre-commit code review 流程的,这一步刚好接”开 PR”前。

什么时候适合用

任何非琐碎 PR——超过 3 个文件、或者动到公共 API / 数据。一行 typo fix 跳过,PR 正文比 prompt 还短。重构 PR、依赖升 PR 尤其值——diff 大但意图小。

开始前准备

  • 分支已经 rebase 到 main(或默认分支)、diff 干净——没有 merge commit 把历史搅乱。
  • 本地测试在分支上能过。过不了先修;AI PR 正文掩盖不了红 CI。
  • 知道 merge base:git merge-base HEAD main。reviewer 看的就是对 merge base 的 diff。
  • 已配好一个 AI 编程工具:Claude Code、Cursor Composer、Codex 或 Aider。下面这段 prompt 在每个里都跑得通,微调即可。

具体步骤

  1. 在分支上把对 main 的 diff 输出到临时文件,方便喂给 AI:
git diff main...HEAD > /tmp/pr.diff
git log main..HEAD --oneline > /tmp/pr.commits
wc -l /tmp/pr.diff  # 看看大小
  1. diff 超过 ~3000 行就拆。要么按目录(git diff main...HEAD -- src/api/-- src/web/),要么按 commit 各总结。喂 1 万行 diff 出来的描述很空。
  2. 在仓库里打开 AI 工具。Claude Code:claude 然后贴下面的 prompt。Cursor:打开 Composer、@ diff 文件。Aider:/add /tmp/pr.diff 再提。
  3. 用结构化 prompt(下一节),要 Summary / Why / Test plan / Risks,并禁止编造测试。
  4. 批判性地读输出。Summary 和 Why 一般还行。Test plan 是 AI 最爱撒谎的地方——逐条对照 diff 里的真实测试文件核。
  5. 就地改。Summary 收成一句。Why 砍到两句。Test plan 里对不上真实测试文件的条目重写。Risks 加上 AI 漏掉的(你懂代码库,它不懂)。
  6. 终稿粘进 PR。工具支持 gh pr create(Claude Code 走 shell 可以、Codex 偶尔原生)就直接喂正文。

一段”逼它说实话”的 prompt

这段稳定产出能审的 PR 正文。存成可复用片段——Claude Code 的 slash command、Cursor rules snippet、或 shell 函数:

你在写 PR 描述。输入:git diff 和 commit 列表。

按这个结构输出,不要前言:

## Summary
<一句话——这个 PR 做了什么,能用用户可见的话就用>

## Why
<2-3 句——底层原因。修 bug?为 X 重构?解锁 Y?>

## Test plan
<列表。只能列对应 diff 里真实测试文件的项,或者 reviewer 能复现的手动步骤。不要编造 diff 里不存在的测试。没加测试就写"未加自动测试。手动验证:<步骤>"。>

## Risks
<列表,可能坏掉的东西。具体——点出文件名、行为、受影响用户。真心低风险就写"低风险:<原因>"。>

约束:
- 不要营销腔("enhances"、"improves"、"leverages")。
- 文件路径用反引号包。
- diff 里意图不明就直说——不要猜。

“不要编造测试”那句是承重的。少了它,几乎每个 AI 工具都会幻觉出根本不存在的测试覆盖。

完成后检查

  • Summary 一句话,reviewer 不用回去再看 diff 就能复述。
  • Why 讲动机不讲机制。Why 在复述 Summary 就重写。
  • 每条 Test plan 对应 diff 里的真实测试文件(用 git diff main...HEAD -- '**/*test*' 验)或一个手动步骤。
  • Risks 点出具体文件或行为,不是”可能影响性能”这种废话。
  • 没营销腔。“enhances”、“leverages”、“robust”——划掉。
  • 长度:中等 PR 6-15 行。再长 reviewer 跳过;再短啥也没说。

怎么复用这套流程

  • 上面的 prompt 存成 Claude Code slash command(~/.claude/commands/prdesc.md)或 Cursor snippet。一键触发很关键。
  • 重复类型的 PR(依赖升、生成代码更新),做一份更紧的变体只填类型特定部分。
  • 配合AI pre-commit code review 流程——先 review diff 有没有问题、再描述它。
  • 巨型 PR(PR 太大 merge 不动),先生成 PR 描述;一句话讲不清就是 PR 要拆。

建议的操作流程

rebase → 对 merge base 出 diff → 用结构化 prompt 喂给 AI → 复核 Test plan → 就地改 → 粘进 PR。

容易踩的坑

  • 不查就信 AI 的 Test plan。最常见的幻觉就是”加了 X 的单元测试”,diff 里根本没那个测试文件。
  • 喂整个仓库进上下文不只喂 diff。AI 注意力被未改代码稀释,描述变得通用空洞。
  • 不 rebase。带 merge commit 的乱 diff 出乱描述。
  • prompt 含糊(“给这个写个 PR 描述”)。没结构化形状,AI 默认营销腔。
  • 不改输出。再好的草稿也要花 30 秒人工清;生 AI 正文有一股气味 reviewer 闻得出来。
  • 小 PR 也这么搞。一行修复用不着四节正文;写一句话就行。

FAQ

  • 用哪个模型最好?: Sonnet 4.6 或 GPT-5 都行;diff 异常复杂用 Opus 4.7。更快模型(GPT-5.4)偶尔会漏掉”不编造测试”那条约束——盯一下。
  • Conventional Commits 项目能用吗?: 能——prompt 里加”按 Conventional Commit 格式:type(scope): summary,然后是正文”。
  • CI 自动生成 PR 正文呢?: Claude Code --message 或 GitHub Actions 的 Claude 集成可以无人值守跑。没人在 loop 里时复核 pass 要更严。
  • 自动化里怎么让 Test plan 不撒谎?: 把 git diff main...HEAD -- '**/*test*' 也喂进 prompt,指示:“Test plan 只能引用这段 diff 里出现过的文件名。“

相关阅读

标签: #AI 编程 #工作流