大多数”AI 帮我写 changelog”的产出是一堆 commit message 的堆叠,没人会读。原因很简单:git log 是作者在提交那一刻写给自己看的,release note 是发布那一刻写给读者看的。受众不同,措辞当然不一样。这套流程让你从原始 commits 走到”两层 release note”(一层给用户,一层给开发者),同时不丢掉让这份说明值得信任的技术准确性。
这篇主要解决什么问题
一个可复用的流程:用真实输入(git log v1.2.0..HEAD --oneline、合并的 PR 标题、关闭的 issue 编号)让 AI 生成 release note,再做一次评审把 AI 容易漏的东西抓出来——用户可见的行为变化被一条 “refactor” commit 藏掉、breaking change 被 “chore:” 前缀盖住。
这篇适合谁看
每周或双周发版的维护者、产品快速迭代的独立开发者、自己要写 release note 但不想花一小时读 45 条 commit 的技术负责人。
什么时候适合用
20-100 条 commit 的版本,面太大,没有人能记全所有改动。提交信息有点规范(feat:、fix:、chore:)的 semver 仓库。结束 sprint 的 release note,受众混杂——用户、客服、工程师都看同一份。
什么时候不建议用
安全发布——措辞太重要,不能让模型转述 CVE 描述。完全无规范的 tag(满屏 “wip”)——AI 无可依据,会瞎编。极小的 patch 版本(1-3 条 commit)——自己 2 分钟写完。
开工前
- 选好 tag 区间。
git log v1.2.0..HEAD --oneline是标准输入。不打 tag 就用上次发布的 SHA。 - 同时拉 PR 标题和 label——往往比 commit message 更能表达用户视角的意图。
gh pr list --state merged --search "merged:>2026-05-01"即可。 - 提前决定层级。多数项目正好两层:“给用户”(行为变化、新功能、breaking change)和”给开发者”(内部重构、依赖升级、基础设施)。库项目一层就够。
- 把上一版 changelog 翻开。语气、章节顺序、分类名要一致——读者已经认了你的格式,没理由就改是负分。
具体步骤
- 生成原始输入。一个中等规模的版本:3 周内 45 条 commit。
git log v1.2.0..HEAD --oneline > /tmp/commits.txt gh pr list --state merged --base main --search "merged:>=2026-05-01" \ --json number,title,labels > /tmp/prs.json - 一条消息把两份都贴上。告诉模型你要的层级和章节名(Added / Changed / Fixed / Removed,或你项目用的那套)。
- 先只要”分类”,不要文案。“按 Added / Changed / Fixed / Removed 分组,每条 commit 一行,保留 PR 编号。“分错类很容易此时发现,回头修改成本低。
- 评审分组。错位的挪走。一条 “fix:” 其实是新功能,挪到 Added。一条 “refactor:” 改了用户可见的默认值,挪到 Changed。
- 让模型把”给用户”那一层重写成非工程师能读懂的话。“重写 Added / Changed / Removed,给非工程师读者。跳过纯内部重构。“这一步才是把 release note 和 commit dump 区分开的地方。
- 让模型把”给开发者”那一层原样保留:依赖升级、重构、test-only、不可见的改动都放这。
- 把两层都念一遍出声。读起来卡的就重写。然后逐条确认每个 breaking change 都明确写出来,并附迁移说明。
能产出诚实输出的 Prompt
这是 v1.2.0..v1.3.0 的 45 条 commit:
\{粘 git log --oneline\}
这是合并的 PR 标题和 label:
\{粘 gh pr list JSON\}
产出一份 release note,两层:
1. "给用户"——只写用户可见的变化(新功能、行为变化、影响用户的
bug 修复、带迁移说明的 breaking change)。说人话。不要内部术语。
2. "给开发者"——内部重构、依赖升级、infra、test-only、其他用户
不可见的改动。
每层内部按 Added / Changed / Fixed / Removed 分组。括号里保留 PR 编号。
规则:
- 不要编造功能。commit 不清楚就标 "[不清楚 — 需复核]",我来检查。
- 不要弱化 breaking change。前缀写 "Breaking:" 并附一行迁移说明。
- 不要把不相关的 commit 合成一行。
质量检查
- 每个 breaking change 都标 “Breaking:” 并附迁移说明。AI 倾向于把这些埋掉——重新 grep diff 里所有 API 变更,逐一对应。
- 没有编造的功能。听起来像新东西的,回去对原始 PR。一条单行 commit 被扩成一段许诺多于实际发布的话,模型常这么干。
- 用户层没有内部术语。“重构了 FooService” 这种话要挪到开发者层。
- 条数大体对得上。45 条 commit 进,20-35 行出。AI 给你 12 行就是压得太狠。
- 语气和上一版 changelog 一致。让人觉得是同一个人写的。
怎么把这流程沉淀下来
- 把两层的 prompt 存成片段。同一份模板版本间复用,只换输入。
- 维护一份 “Breaking change 检查清单”——API 删除、默认值变化、要求的迁移步骤。每版重查。
- 写个小脚本,把
git log+gh pr list一并跑出来,输出成可直接粘贴的文件。摩擦减 90%。 - 每发完一版,把分错类的项作为示例加进 prompt,下次更准。
建议的操作流程
git log v1.2.0..HEAD + PR 标题 → AI 分 Added / Changed / Fixed / Removed → 人评分组 → AI 把用户层改成人话 → AI 输出开发者层原样 → 人念出声 → 发布。45 条 commit 的版本,20-30 分钟,对比手写 90 分钟。7 个章节的 release note 一般要修正 3-4 轮。
容易踩的坑
- 只贴
git log,不附 PR 标题。Commit 写得简,PR 标题才有意图。直接丢掉一半信号。 - 不分组就让 AI 直接写用户层。错位的项一路混到终稿。
- 跳过念出声。AI 的别扭句式会留下来,整体一股机器味。
- 在 breaking change 上信任 AI。它会把”Removed X”软化成”Updated X”。每个 removal 必须人复核。
- 用在安全发布上。措辞太重要,手写。
FAQ
- commit message 写得差怎么办?: AI 还能从 PR 标题 + issue 引用拼出一稿,但质量会断崖。长期看,要投资 commit 规范(conventional commits、PR 模板)。
- AI 能按章节自动归类 PR 吗?: 能,如果 PR 有 label(
type:feature、type:fix)。label 比 message 信号更强。有就用。 - 能让它写顶部那一句总结吗?: 草稿可以,发布不行。release note 顶上那一句是用户唯一一定会读的——正文定稿之后自己写。
- 按贡献者归属呢?: 项目要署名贡献者,让模型保留作者。
git log --pretty='%h %an %s'给你输入。发布前对一遍真实贡献者名单。