用 AI 写 commit message 与 PR 描述
commit message 和 PR 描述是开发者最懒得写、又最有价值的文档之一。AI 能从 diff 自动生成高质量的它们。本文讲清怎么用 AI 生成符合规范的 commit(Conventional Commits)、PR 描述(动机/变更/测试/风险),以及怎么集成进 git hook/CI,让"懒得写"不再是借口。
本文要点
- 主题聚焦:Vibe Coding、TypeScript
- 适合人群:独立开发者、全栈工程师、AI 应用开发者
- 核心价值:快速理解背景、实践路径、常见误区和工程建议
用 AI 写 commit message 与 PR 描述
先承认一件事:绝大多数开发者的 commit message 是垃圾。fix bug、update、wip、111、final final v2——你我他都写过。PR 描述也好不到哪去,要么一片空白,要么一句"改了下登录"。
这不是态度问题,是经济学问题。写一条好 commit 的收益在未来(半年后排查线上故障、新人 onboarding、发版写 changelog),成本却在当下(我现在只想 push 下班)。人天生短视,AI 恰好能把"当下的成本"压到接近零。本文讲怎么用 AI 把 commit message 和 PR 描述这件事,从负担变成顺手。
一、为什么 commit message 和 PR 描述值得认真对待
一句话:git log 是一个项目最诚实的编年史,PR 描述是每一章的序。代码会重构、文档会过期、架构图会骗人,但 commit 历史忠实记录了"谁、在什么时候、为什么改了这行代码"。
它有三个不可替代的价值:
- 回溯:线上炸了,
git bisect或git log -S定位到某次提交,一条说清"为什么改"的 message 能救你一晚上;一条fix bug让你抓狂。 - 协作:Reviewer 读 PR,先看描述再看 diff。描述写清楚了,review 效率翻倍,也省得你在评论区反复解释动机。
- 发版:release notes、changelog、对外公告,源头都是 commit 和 PR。源头烂了,下游全靠编。
现实是:大家都懂这些道理,但 deadline 面前没人愿意花三分钟组织语言。所以解决方案不是"教育开发者",而是把写它的成本降到趋近于零——这正是 AI 的活儿。
二、AI 生成 commit message:让 diff 自己说话
AI 生成 commit 的核心机制很朴素:把暂存区 diff 喂给模型,让它输出一条符合规范的 message。关键不在"AI",在"符合规范"。
业界事实标准是 Conventional Commits,格式长这样:
<type>(<scope>): <subject>
<body>
<footer>
type:feat/fix/perf/refactor/docs/test/chore/build/ci/style/revertscope:影响的模块(可选,但强烈建议),比如auth、checkout、dbsubject:祈使句、现在时、不长于 50 字,结尾不加句号body:解释"为什么"而不是"改了什么"(diff 已经说明改了什么)footer:破坏性变更用BREAKING CHANGE:,关联 issue 用Closes #123
给 AI 的 prompt 大致是这个套路(伪代码):
你是资深工程师。下面是一次 git diff,请生成一条 Conventional Commits 格式的 commit message。
要求:
1. type 必须从 [feat,fix,perf,refactor,docs,test,chore,build,ci,style,revert] 中选,不准编造。
2. scope 根据改动的模块推断,拿不准就省略。
3. subject 不超过 50 字,祈使句,不加句号。
4. body 说明动机和影响,如果改动简单可以省略。
5. 若有 API/行为不兼容,footer 必须以 BREAKING CHANGE: 开头。
6. 只输出 message 本身,不要解释。
<diff>
{{ diff 内容 }}
</diff>
真实 diff 是锚点——没有 diff,AI 只能猜;有了 diff,它生成的 message 比大多数人手写的还规矩。比如你改了 src/auth/jwt.ts 里 token 刷新逻辑,AI 会给出 fix(auth): 在 token 即将过期时主动刷新,避免并发请求 401,比你硬憋一句"fix token"信息量大十倍。
现成工具不少:aicommits(开源 CLI,npm i -g aicommits)、opencommit、或者直接在 Claude Code / Cursor 里让它读 git diff --cached 生成。底层都一样:diff 进,message 出。
三、AI 生成 PR 描述:四个必填块
PR 描述比 commit message 更重要,因为它要说服别人合并你的代码。我固定用一套模板,AI 也照这套填:
## 动机
为什么要做这个改动?解决了什么问题?关联 issue / 设计文档。
## 主要变更
- 改了什么(高层概括,不要复述 diff)
- 有没有行为变化
## 测试方式
- 怎么验证的?跑了哪些测试?手动验证了什么场景?
## 风险 / 破坏性
- 可能影响什么?有没有不兼容?
- 回滚方案
这四块对应了 reviewer 心里的四个问题:为啥改、改了啥、靠谱不、会不会出事。一块都不能少。
AI 在这里的价值不只是"写字",而是强迫结构化。你随手写的 PR 描述很容易漏掉"风险"那一栏,但 AI 每次都会老老实实填上——哪怕写的是"本次改动无破坏性风险",也比空白强,因为它逼你想了一秒。
给 AI 的输入应该是这次 PR 的完整 diff(gh pr diff 或 git diff main...feature),加上 PR 标题和关联 issue 的简述。输出就是上面这个结构化模板。
四、集成进 git hook、CLI 和 CI
光有 prompt 没用,得让它在"对的时机"自动跑起来。三个集成点:
1. git hook:prepare-commit-msg 自动生成
prepare-commit-msg 钩子在编辑器打开前触发,正好用来预填 message。脚本大致这样(放在 .git/hooks/prepare-commit-msg,或用 husky/lefthook 管理):
#!/bin/sh
COMMIT_MSG_FILE=$1
COMMIT_SOURCE=$2
# merge / squash / cherry-pick 等场景直接放行
[ -n "$COMMIT_SOURCE" ] && [ "$COMMIT_SOURCE" != "template" ] && exit 0
DIFF=$(git diff --cached)
[ -z "$DIFF" ] && exit 0
# 调用 AI 生成,结果写入 COMMIT_MSG_FILE
echo "$DIFF" | ai-commit > "$COMMIT_MSG_FILE"
# 打开编辑器让你 review,而不是直接提交
注意一个细节:这个钩子只是预填,编辑器照样会打开,你有机会改。这一点很重要——AI 是助手不是自动驾驶,后面会展开。
2. CLI:手动触发,适合尝鲜
不想一上来就改 hook,可以先用 CLI 手动跑:
git add -p
git diff --cached | ai-commit | git commit -F - # 把输出直接当 message
或者更简单,在 Claude Code 里直接说"根据当前暂存区 diff 写一条 commit",它会把 message 给你,你确认后再提交。
3. CI:PR 创建时自动评论
团队层面最有用的是 CI。新建 PR 时跑一个 job,读 PR diff,生成结构化描述,以评论形式贴上去(而不是覆盖作者写的正文,这是礼貌):
# .github/workflows/ai-pr-description.yml
name: AI PR Description
on:
pull_request:
types: [opened]
jobs:
describe:
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 0 }
- name: Generate and comment
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
gh pr diff ${{ github.event.pull_request.number }} > pr.diff
DESCRIPTION=$(ai-pr-describe < pr.diff)
gh pr comment ${{ github.event.pull_request.number }} \
--body "$DESCRIPTION"
新人入职第一天提 PR,CI 自动给他补一份像样的描述,团队 review 体验立刻上一个台阶。
五、质量把控:别给 AI 自由发挥的权限
AI 写 commit 翻车的根因永远是同一个:脱离 diff 瞎编。守住质量有几条铁律:
- 必须基于真实 diff。没有 diff 就别生成——宁可空着。这是防范幻觉的根本。
- 格式强约束。type 限定白名单、subject 限长、body 可选。用 schema 校验,格式不对直接打回。
- 人工可改、必须能改。AI 生成的永远是草稿,编辑器/评论区要留给作者修改的空间。我见过团队把 hook 设成"生成完直接 commit 不打开编辑器",结果上线后幻觉 message 混进主分支,得不偿失。
- 大改动分多次 commit 再分别生成。一个 commit 塞了重构 + 新功能 + bugfix,AI 只能给你一条含糊的
feat: 大改了一波。正确做法是git add -p把改动拆细,每个原子 commit 单独喂给 AI——这时它的表现最好。
六、陷阱:幻觉、过度细节、漏掉破坏性变更
用了一段时间你会踩到三个坑:
- 幻觉:AI 偶尔会"补全"diff 里没有的改动,比如 message 里写"同时修复了缓存失效逻辑",但 diff 压根没碰缓存。对策:review 时拿 message 和 diff 对照,凡是 diff 里没有的一律删掉。
- 过度细节:把每个文件名、每个变量都罗列一遍,body 写成 diff 的自然语言翻译。好 message 讲"为什么",不讲"改了哪几行"。prompt 里明确"不要复述 diff"能缓解。
- 忽略破坏性变更:这是最危险的。AI 倾向于报喜不报忧,把删字段、改返回值这类不兼容变更轻描淡写成
refactor: 清理接口。对策:prompt 里重罚——"任何可能影响调用方的改动,必须在 footer 用 BREAKING CHANGE 标注,宁可误报不可漏报"。
一句话:AI 生成的 commit 和 PR 描述,必须 review,和 review 代码一样认真。
七、进阶:从一组 commit 自动生成 release notes
commit 写规范了,最大的红利在发版时兑现。发版时把两个 tag 之间的所有 commit 喂给 AI:
git log v1.4.0...v1.5.0 --pretty=format:"%s%n%b" > commits.txt
ai-changelog < commits.txt > RELEASE_NOTES.md
让 AI 把几十条 commit 聚合成人话:
## v1.5.0
### 新功能
- 支持断点续传,大文件上传中断后可恢复
### 修复
- 修复高并发下 token 刷新竞态导致的偶发 401
### 破坏性变更
- `getUser()` 返回结构中 `name` 字段改为 `displayName`,老代码需适配
这就是 Conventional Commits + AI 的飞轮:每次 commit 多花 5 秒生成规范 message,发版时省下两天的 changelog 编写时间。规范在源头,红利在下游。
小结
- commit message 和 PR 描述是项目最被低估的文档,价值在回溯、协作、发版,痛点在"当下成本高"。AI 把成本压到趋近零,是性价比最高的 AI 编程落地之一。
- 机制很朴素:真实 diff 进,规范 message 出。锚点是 diff,规范是 Conventional Commits。
- PR 描述固定四块:动机、主要变更、测试方式、风险/破坏性。AI 的价值不只是写字,更是强迫结构化。
- 三个集成点:
prepare-commit-msg钩子预填、CLI 手动触发、CI 在 PR 创建时自动评论。 - 铁律是 review:基于真实 diff 防幻觉、格式强约束、人工可改、大改动拆分。AI 是助手,不是自动驾驶。
一句金句收尾:让 AI 写 commit,不是偷懒,是把工程师的脑力从"组织语言"解放出来,留给真正该想的"为什么改"。规范在源头,红利在下游——这一笔投资,稳赚。
Related