AI 生成更新日志:从 commits 到人愿意读完的 release note

把 git log 变成读者真会读完的两层 release note,再用一道评审抓出被藏起来的 breaking change。

大多数”AI 帮我写 changelog”的产出,是一堆 commit message 的堆叠,没人会读完。原因是结构性的:git log 是作者在提交那一刻写给自己看的,release note 是发布那一刻写给读者看的。受众不同,措辞当然不一样。这套流程让你从原始 commits 走到”两层 release note”(一层给用户,一层给开发者),同时不丢掉让这份说明值得信任的技术准确性。

TL;DR

  • git-cliff、GitHub 自带的 release notes 这类确定性工具,能免费按类型把 commit 和 PR 分好组。它们快,且绝不瞎编。把它们当作底线。
  • 大模型(截至 2026 年 6 月,Claude Sonnet 4.6 或 GPT-5.5)真正值这个钱的只有一件事:把面向用户那一层重写成非工程师能读完的人话。
  • 流程是:先用确定性工具分组,再让 AI 只重写用户层,最后人做一道聚焦 breaking change 的评审。
  • 45 条 commit 的版本,这样走 20-30 分钟,对比手写约 90 分钟。
  • 永远不要只贴 git log。PR 标题和 label 带着 commit 漏掉的意图。

AI 该用在哪一段(不该用在哪)

changelog 工具是一条从完全确定性到完全生成式的光谱,每一档各擅长一件事。

方式做什么会瞎编吗适合
git-cliff用 Tera 模板把 Conventional Commits 解析成 Keep a Changelog 章节;1 万条 commit 约 120 毫秒不会commit 规范严格的库 / CLI 仓库
release-please / semantic-release按 commit 类型升版本号、开 release PR、写 CHANGELOG不会CI 驱动的 semver 自动化
GitHub 自动笔记(gh release create --generate-notes按 label 列出合并的 PR、署名贡献者、附完整 diff 链接不会GitHub 原生的快速发布页
AI 重写(本流程)把分好组的 commit 按受众层翻译成面向读者的文字不复核就会用户、客服、工程师看同一份的混合受众 release note

确定性工具不会幻觉,但也永远不会解释”用户为什么该在意”。这件事正是 AI 来做的,也是 git-cliff 模板做不到的。所以最稳的打法是把它们叠起来:先让确定性工具产出分好组的骨架,再让模型只重写用户层。

这篇适合谁看

每周或双周发版的维护者、产品快速迭代的独立开发者、自己要写 release note 但不想花一小时读 45 条 commit 的技术负责人。

什么时候适合用

20-100 条 commit 的版本,面太大,没人记得全所有改动。提交信息至少有点 Conventional Commits 规范(feat:fix:chore:)的 semver 仓库。结束 sprint 的 release note,受众混杂——用户、客服、工程师都看同一份。

什么时候不建议用

  • 安全发布。措辞太重要,不能交给模型,更不能让它转述 CVE 描述。Security: 条目手写。
  • 完全无规范的 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 翻开。语气、章节顺序、分类名要一致,读者已经认了你的格式,没理由就改是负分。如果还没定格式,Keep a Changelog 那六个章节(Added、Changed、Deprecated、Removed、Fixed、Security)是大家都认的默认值。

具体步骤

  1. 生成原始输入。一个中等规模的版本: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
  2. 能确定性分组就先分。跑 git-cliff v1.2.0..HEAD(它遵循 Conventional Commits,输出 Keep a Changelog 章节),或 gh release create v1.3.0 --generate-notes --draft 拿 GitHub 原生的 PR 列表。这份骨架就是你的事实底座,模型可漂移的空间更小。
  3. 把骨架(或原始输入)贴进一条消息。告诉模型你要的层级和章节名。
  4. 先只要”分类”,不要文案。“按 Added / Changed / Fixed / Removed 分组,每条 commit 一行,保留 PR 编号。“此时分错类很容易发现,回头修改成本低。
  5. 评审分组。错位的挪走。一条 fix: 其实是新功能,挪到 Added;一条 refactor: 改了用户可见的默认值,挪到 Changed。带 !BREAKING CHANGE: 脚注的是大版本信号,确保它浮出来。
  6. 让模型把”给用户”那一层重写成非工程师能读懂的话。“重写 Added / Changed / Removed,给非工程师读者,跳过纯内部重构。“这一步才是把 release note 和 commit dump 区分开的地方。
  7. 让模型把”给开发者”那一层原样保留:依赖升级、重构、test-only、不可见的改动都放这。
  8. 把两层都念一遍出声。读起来卡的就重写。然后逐条确认每个 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 合成一行。

当下任何一线模型都能很好地处理。截至 2026 年 6 月,Claude Sonnet 4.6 和 GPT-5.5 都标配 1M token 上下文(在 ChatGPT 应用内用满 1M 需 $200 Pro 档),所以哪怕 200 条 commit 的版本也能整段贴进去。模型选哪个,没那道评审重要。

质量检查

  • 每个 breaking change 都标 “Breaking:” 并附迁移说明。AI 倾向于把这些埋掉,重新 grep diff 里所有 API 变更,逐一对应。再对照 git log 里的 ! 标记和 BREAKING CHANGE: 脚注。
  • 没有编造的功能。听起来像新东西的,回去对原始 PR。一条单行 commit 被扩成一段、许诺多于实际发布的话,模型常这么干。
  • 用户层没有内部术语。“重构了 FooService” 这种话要挪到开发者层。
  • 条数大体对得上。45 条 commit 进,20-35 行出。AI 给你 12 行就是压得太狠。
  • 语气和上一版 changelog 一致,让人觉得是同一个人写的。

怎么把这流程沉淀下来

  • 把两层的 prompt 存成片段。同一份模板版本间复用,只换输入。
  • 维护一份 “Breaking change 检查清单”:API 删除、默认值变化、要求的迁移步骤。每版重查。
  • git-cliff(或 gh release --generate-notes)接进一个脚本,把分好组的骨架加上原始 git loggh pr list 一并输出成可直接粘贴的文件。这能去掉大部分摩擦,也给了模型一层确定性的事实底座。
  • 每发完一版,把分错类的项作为示例加进 prompt,下次更准。

建议的操作流程

git-cliff(或 git log + PR 标题)产出分好组的章节 → AI 把用户层改成人话 → AI 输出开发者层原样 → 人复核 breaking change 并念出声 → 发布。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 必须人对着 diff 复核。
  • 用在安全发布上。措辞太重要,手写。

FAQ

  • 直接用 git-cliff 或 GitHub 自动笔记、跳过 AI 不行吗?: 分组就该用它们,确定性、绝不瞎编。但它们原样输出 commit 主题,于是用户读到的是 “fix: null guard in token refresh”,而不是”修复了慢网下被登出的问题”。AI 唯一的活就是这道翻译。两者搭着用。
  • commit message 写得差怎么办?: AI 还能从 PR 标题 + issue 引用拼出一稿,但质量会断崖。长期看要投资 commit 规范(Conventional Commits、PR 模板),确定性工具也才跑得起来。
  • AI 能按章节自动归类 PR 吗?: 能,如果 PR 有 label(type:featuretype:fix)。label 比 message 信号更强。GitHub 自动笔记也按 label 分组,设一次两层都受益。
  • 能让它写顶部那一句总结吗?: 草稿可以,发布不行。release note 顶上那一句是用户唯一一定会读的,正文定稿之后自己写。
  • 按贡献者归属呢?: 项目要署名贡献者,让模型保留作者。git log --pretty='%h %an %s' 给你输入,发布前对一遍真实贡献者名单。GitHub 自动笔记会自动署名贡献者。

相关阅读

标签: #AI 编程 #工作流