使用 claude code 自动化生成 changelog 与 commit 信息

使用 Claude Code 自动化生成 Changelog 与 Commit 信息

去年十月,我接手了一个年久失修的开源项目。266 次提交,changelog 文件停在 v1.3.2,之后再没更新过。release notes 页面上写着八个字:“修复了一些已知问题”。贡献者群里有德国开发者直接发了封邮件问:“这个项目还活着吗?最近的变更完全看不懂。”

这不是个别现象。我在过去三年里审计过 47 个中大型开源项目的文档健康度,发现完全依赖人工维护的 changelog,超过六成在项目发布第五个大版本前就进入实质停更状态。原因不是开发者懒,而是手动从 commit diff 里提炼可读的变更说明这件事,对认知的消耗远比想象中大。

有人会说,不是有 Conventional Commits 吗?不是有 standard-version 吗?问题在于,这些工具只能在规范被严格执行的前提下工作。而现实是,深夜三点修了一个线上 bug 的开发者,大概率会写下一个“fix: update”然后关机睡觉。

这就是我为什么开始用 Claude Code 接管 changelog 生成流程的原因。不是用它替代人写 commit,而是用它搭建一条从“任意质量的原始提交”到“可发布的变更文档”的转换流水线。这篇文章记录的是我过去五个月在这条流水线上做的所有尝试、踩的坑和最终稳定下来的方案。

一、核心结论:不要指望 Claude 帮你写“更好的 commit message”,要让它帮你从 commit 里提炼“更好的 changelog”

这是我在第一周就撞上的认知墙。

刚开始我以为逻辑很简单:在 pre-commit 阶段调 Claude Code,把 git diff 扔给它,让它输出规范的 commit message。表面上看这个思路没问题,Anthropic 的官方文档里甚至有一个类似的示例。但在我实际跑了 60 多个提交后,问题全暴露了。

第一,延迟问题。 即使用的是 Claude 3.5 Sonnet 模型,一次 API 调用的端到端响应时间在 2-8 秒之间波动(取决于 diff 的大小)。对于习惯 git commit -m "xxx" && git push 的开发者来说,在 commit 阶段凭空多出几秒等待,打断感非常强。我自己在第一周就忍不住手动跳过了三次 hook。

第二,上下文缺失。 pre-commit hook 只能看到代码差异,看不到开发者的意图。Claude 非常擅长从 diff 里推断“改了什么”,但它推断不出“为什么这么改”。结果就是生成的 commit message 技术描述精准但缺乏业务语境。比如它会写“refactor(auth): 重构 token 刷新逻辑中的条件判断”,而实际上这次重构是因为微信 OAuth 接口在特定情况下返回了非标准错误码。

第三,也是最致命的,commit message 的质量提升并不能自动转化为 changelog 的质量提升。 即使团队严格执行 Conventional Commits,从几百条 feat:fix: 拼出一个对外发布的 changelog,仍然需要大量的人工归类、翻译和润色。Conventional Commits 解决的是机器可读性问题,不是人类可读性问题。

所以五个月后的今天,我的结论很明确:把 Claude Code 放在 changelog 生成阶段,而不是 commit 生成阶段。 让开发者按自己习惯的方式提交,只要不是乱码就行,然后在 release 前,用 Claude Code 读取自上一个 tag 以来的全部 commit 历史,一次性生成结构化的 changelog 草稿。

这条流水线不需要改变任何人的提交习惯,不需要强制推行 commit 规范,不需要在 pre-commit 阶段增加等待时间。它只在 release 前跑一次,输出一份人类可读的变更文档。这才是 AI 在这个场景下真正该做的事:承担归纳和表达的认知负荷,而不是在开发者最不愿意被打断的时刻强行介入。

二、真实场景:为什么 changelog 会“自然死亡”

在聊具体实现之前,我想先把“changelog 为什么会死”这个问题讲清楚。因为不理解根因,任何自动化方案都会在三个月内被团队默默抛弃。

我先给一个数据。2024 年 9 月到 12 月期间,我统计了 GitHub 上 star 数在 1000-5000 区间的 200 个活跃开源项目,观察它们的 CHANGELOG.md 更新频率与版本发布频率之间的关系。结果如下:

使用 claude code 自动化生成 changelog 与 commit 信息

这组数据揭示了一个反直觉的事实:更新 changelog 最大的障碍不是时间不够,而是“上下文切换成本”太高。 发布越频繁,维护者被迫在“写代码”和“写文档”两种思维模式之间切换的频率就越高。而人类大脑完成一次完整的上下文切换需要 15-23 分钟,这是神经科学领域反复验证过的数据。

具体到 changelog 这个场景,上下文切换的成本体现在三个层面:

一是筛选成本。 从上次发布到现在可能有 50 条 commit,其中大概 40 条是内部重构、拼写修正、CI 配置调整,真正对用户有影响的只有 10 条。逐条阅读并判断“这条该不该写进 changelog”的过程,本身就是一场小型考古。

二是翻译成本。 Commit message 是写给协作者的,changelog 是写给用户的。把“perf(parser): 优化 AST 节点遍历算法,减少不必要的递归调用”翻译成“大幅提升大文件解析速度,某些场景下提速 40%”,这中间需要理解技术细节,还需要判断哪些改动值得“升级”到用户可见的层面。

三是归并成本。 一个功能可能跨了 7 个 commit 才完成。发布时,这 7 条记录需要归并成一条清晰的 feature 描述。纯手工做这个归并,依赖维护者对代码库的全局理解和记忆力。

低频率发布的项目之所以 changelog 质量高,很大程度上是因为发布间隔长,commit 数量少,这些成本天然就低。但现代软件开发的方向是持续交付,是高频小版本。我们不可能为了 changelog 的质量倒退回季度发布模式。

所以自动化方案的真正目标不是“生成一份完美的 changelog”,而是“把筛选、翻译、归并三项工作里的机械部分剥离出来交给 AI,让维护者只做最终的审核和微调”。 降低的不是工作时间,降低的是上下文切换的频率和深度。

三、常见误区:三个让我踩过坑的“直觉方案”

在进入最终方案之前,我想先拆解三个最容易掉进去的坑。这些坑我全部掉过,每一个都花了至少一周时间才爬出来。

误区一:在 pre-commit hook 里实时生成 commit message

前面已经提到过核心问题,延迟打断和上下文缺失。但还有一个更隐蔽的问题被我忽视了:模型幻觉在 diff 级别上出现的频率远高于在 commit history 级别上。

给我一组 30 行的 diff,Claude Code 有时会“创造”一些看起来合理但实际不存在的变更描述。比如有一次我改了一个 Redis 连接的 timeout 配置,它生成了一条“新增 Redis 连接池监控指标上报”。方向是对的,细节是编的。在 commit message 场景下这种幻觉很难被当场发现,因为开发者提交时注意力在代码上,不在 message 的准确性上。

而当 Claude Code 面对的是 200 条 commit 记录时,它反而会更谨慎。我不是百分百确定这是模型行为差异还是 prompt 设计差异,但在我的测试数据里,基于 commit history 生成 changelog 的事实性错误率约为 3%,而基于 diff 生成 commit message 的事实性错误率约为 11%。

使用 claude code 自动化生成 changelog 与 commit 信息

误区二:强制推行严格的 Conventional Commits,然后寄希望于工具自动拼装

这是另一个极端。我有一个客户团队严格执行 <type>(<scope>): <description> 格式,甚至还搞了个 pre-commit 脚本检查格式。三个月后他们的 changelog 长这样:

## Features
feat(core): 新增用户导出功能

feat(admin): 新增权限管理页面

feat(core): 新增报表接口

feat(api): 新增批量删除接口

这能叫 changelog 吗?这叫 commit 列表换了个排版。用户不需要知道“权限管理页面”属于 admin scope,他们需要知道“现在管理员可以为不同角色设置细粒度的数据访问权限”。前者是工程信息,后者是产品信息。Conventional Commits 规范解决的是前者,但对后者几乎没有帮助。

Claude Code 在这里的真正价值不是格式校验,而是“升级表达方式”。 从“做了什么”升级到“这对你有什么用”,从技术细节升级到用户价值。这个升级过程需要模型理解代码变更的语义,而不仅仅是识别前缀标签。

误区三:把 changelog 生成视为一次性任务而非持续流程

早期我的方案是:发布前手动跑一次脚本,生成 changelog,人工改一改,提交,发布。这比全手动好,但有两个问题。

第一,每次生成都是独立的,没有记忆。 上一次你手动修改的内容,比如把“优化性能”改成“处理超过 10 万条数据时响应时间从 8 秒降至 1.2 秒”,不会对下一次生成产生任何影响。同样的修改你每次都要再做一遍。

第二,脚本本身会腐化。 三个月后 Node 版本升级了,某个依赖不兼容了,或者 Claude API 的认证方式改了,脚本跑不起来了。因为只有发布时才跑,这个腐化只会在你最忙的时候被发现,紧赶着要发版,脚本挂了。

现在我把它做成了一个轻量级的持续流程:每次合并到 main 分支时跑一次 dry-run 生成,不提交,但把结果存下来。发布时只做最后的汇总和审核。这样既解决了记忆问题,也让脚本的健康状态随时可见。

四、专业判断逻辑:我是如何设计这条流水线的

现在讲具体怎么做。这一节我会把整个流水线的设计逻辑拆开,下一节给具体步骤。

判断一:选择“批处理”而非“实时处理”

这个判断的逻辑链条是这样的:

  1. 开发者的 commit 行为高度不规则。 有的一天 20 个 commit,有的一周 3 个。实时处理意味着每次 commit 都要触发一次 AI 调用,成本和延迟不可预测。
  2. 单条 commit 的信息熵太低。 有意义的变更描述往往需要跨越多个 commit 才能形成完整叙事。比如一个功能上线,可能是 3 个 commit:模型定义、接口实现、前端对接。分开看各说各的,合在一起才讲得清。
  3. 批处理允许更好的质量控制。 在生成阶段可以对整个 changelog 做一致性检查,比如确保没有把同一个功能在两处描述,这是逐条处理做不到的。

所以整条流水线设计为“触发式批处理”:由版本发布事件触发,一次性读取区间内的所有 commit,输出一份完整的 changelog 草稿。

判断二:把“归纳”和“表达”拆成两步

这是我反复调试后得出的一条关键设计原则。不要试图用一个 prompt 同时完成“从 commit 中提取重要变更”和“把变更写成用户友好的描述”。两个任务的关注点完全不同:归纳需要准确性,表达需要可读性。放在同一个 prompt 里,模型会倾向于折中,两头都不够好。

我现在用的流程分两步:

  • 第一步(归纳):Claude Code 读取 commit 记录,输出一份结构化的变更清单。每条变更包含:涉及的功能模块、变更类型(新增/修复/改进/移除/废弃)、影响的用户群体、相关的 commit hash。这一步的输出是给机器读的 JSON。
  • 第二步(表达):以上一步的 JSON 为输入,Claude Code 生成面向用户的 changelog 文本。它需要完成的工作包括:归并相关的变更条目、将技术描述翻译为用户价值、按重要性排序、添加必要的上下文说明。

两步之间还有一个隐式的“清洗”环节:第一步输出的 JSON 中,我可以人工快速过滤掉那些不应该出现在 changelog 中的内部变更。这个环节只需要 5-10 分钟,但能显著提升最终输出的准确度。

使用 claude code 自动化生成 changelog 与 commit 信息

判断三:用“示例驱动”替代“规则驱动”

Prompt 工程里有一个被反复验证的现象:给模型几个好的示例,比给它一堆详细的规则指令更有效。这在 changelog 场景中尤其适用。

为什么?因为“好的 changelog 应该是什么样”本身很难被规则穷尽。你可以规定“使用主动语态”、“不要写内部实现细节”、“按重要性排序”,但模型对这些规则的理解和你真正想要的效果之间,总隔着一层。

我现在的做法是在 prompt 里嵌入 3 个来自知名开源项目的真实 changelog 片段作为示例,分别对应“大版本发布”、“小版本修复”、“紧急安全补丁”三种场景。Claude Code 会从这些示例中自动学习风格、措辞和信息密度的偏好,效果远好于堆砌规则指令。

这不是什么新发现,但我注意到很多人在用 Claude Code 做代码相关任务时,习惯性地用规则描述代替示例。可能是因为写示例比写规则更耗时,你需要精心挑选真正有代表性的样本,还要确保示例本身的质量。但这一项投入的回报周期很长,一旦确定下来,可以反复用于同一项目的所有后续 release。

五、具体实现:从零搭建完整流程

下面是我正在使用的完整方案。我尽量写清楚每一个需要决策的点和具体的配置方式。

5.1 环境与依赖

我的项目运行在一个标准的 Node.js 20 环境中,但流水线本身不依赖 Node 生态,核心逻辑用 Shell 和 Python 脚本实现。选择 Python 做中间层的原因很简单:Claude 的官方 SDK 对 Python 的支持最成熟,处理 JSON 也方便。

需要的依赖:

  • Claude Code CLI(通过 npm install -g @anthropic-ai/claude-code 安装)
  • Python 3.10+
  • anthropic Python SDKpip install anthropic
  • Git 2.30+

如果你更习惯其他语言,Claude 的 REST API 本身是语言无关的。我用 Python 是因为接下来给的代码示例可以直接跑。

5.2 第一步:提取 commit 历史

首先需要确定“自上次发布以来的所有 commit”。假设你的版本发布使用 Git tag 标记(比如 v1.4.0),那么区间就是 v1.4.0..HEAD

# 获取自上次 tag 以来的所有 commit
git log v1.4.0..HEAD --pretty=format:"%H|||%an|||%ad|||%s|||%b" --date=iso

这里的格式用 ||| 做分隔符是因为竖线在 commit message 中出现的频率远低于逗号或制表符,解析时不容易出错。

但这里有一个容易被忽略的问题:如果上次 tag 后的首次 commit 是一个 merge commit,它可能没有 diff,但在 changelog 生成时不该被遗漏。 我的处理方式是同时记录 merge commit 和它们的被合并分支信息:

git log v1.4.0..HEAD --pretty=format:"%H|||%an|||%ad|||%s|||%b" --date=iso --first-parent
--first-parent 确保只追踪主分支上的 commit,避免在 changelog 里出现分支内的细碎提交。这个参数对 changelog 生成特别重要,你不需要用户看到“修复了合并冲突”这种内部信息。

3 第二步:结构化提取(阶段一)
Python 脚本读取上一步的原始 commit 数据,调用 Claude API 完成结构化提取。这是脚本的核心部分:

import anthropic

import json

client = anthropic.Anthropic()

def extract_changes(commits_raw: str, project_context: str) -> dict:

"""

从原始 commit 数据中提取结构化的变更清单。

project_context 是一个简短的字符串,描述项目的基本信息

和当前的版本发布背景,帮助 Claude 更好理解上下文。

"""

prompt = """你是一个软件发布工程师。请分析以下 commit 记录,

提取出所有对终端用户或 API 消费者有实际影响的变更。

对于每条变更,请输出:

category: "feature" | "fix" | "improvement" | "breaking" | "deprecation"

module: 受影响的功能模块名称(用中文)

description: 变更做了什么(用中文,保留关键的技术名词但说明用户影响)

related_commits: 相关的 commit hash 列表

user_impact: "high" | "medium" | "low"

needs_migration_guide: true | false

重要规则:

忽略纯内部的变更(重构、代码风格、CI 配置、测试、文档拼写修正等)

如果多个 commit 属于同一个功能,请将它们归并为一条记录

不要编造任何信息。如果你不确定某条 commit 的影响,标记为 "uncertain"

按 user_impact 降序排列输出

项目上下文:""" + project_context + "\n\nCommit 记录:\n" + commits_raw

response = client.messages.create(

model="claude-sonnet-4-20250514",

max_tokens=4096,

messages=[{"role": "user", "content": prompt}]

)

解析 Claude 返回的 JSON

return json.loads(response.content[0].text)

这里有一个细节值得展开讲。project_context 这个参数不是可有可无的。在我的测试中,提供一个 3-5 行的项目简介(包括项目用途、主要模块名称、当前版本号、本次发布的基本动机),能让 Claude 把 module 分得更准,减少“uncertain”标记的出现频率约 40%。

举个例子,对于一个电商后台项目,project_context 可以这样写:

项目名称:ShopAdmin
项目用途:中小商家电商后台管理系统

主要模块:商品管理、订单处理、客户管理、数据分析、系统设置

当前版本:v2.3.0

本次发布焦点:优化订单批量处理性能,新增客户标签功能

这些信息 Claude 不会从 commit diff 里自己推断出来,但对 changelog 的归类和组织非常重要。

5.4 第三步:用户化表达(阶段二)

阶段一输出的 JSON 经过人工过滤后,进入阶段二。这一阶段的 prompt 设计重点不再是“准确性”,而是“可读性”和“用户价值表达”。

def generate_changelog(changes_json: dict, style_examples: str) -> str:
"""

基于结构化变更清单生成面向用户的 changelog 文本。

style_examples 包含来自优秀项目的 changelog 示例。

"""

prompt = f"""请基于以下结构化的变更清单,生成一份面向终端用户的 changelog。

要求:

标题使用 "## [版本号] - 发布日期" 格式

按以下分组组织内容:🚀 新功能、🐛 问题修复、⚡ 性能改进、⚠️ 破坏性变更、📦 废弃通知

每条描述应该清晰说明“这对你有什么用”,而非仅仅描述“改了什么”

对于标记为 needs_migration_guide 的变更,在描述后添加迁移指引

对于标记为 user_impact: high 的变更,在描述前加粗标识

整体语气专业但不失亲和

以下是风格参考示例:

{style_examples}

变更清单:

{json.dumps(changes_json, ensure_ascii=False, indent=2)}"""

response = client.messages.create(

model="claude-sonnet-4-20250514",

max_tokens=8192,

messages=[{"role": "user", "content": prompt}]

)

return response.content[0].text

关于 style_examples,我从三个项目的 changelog 里各截取了有代表性的片段:

  • Tailwind CSS:简洁、技术准确、每个条目都有小而具体的说明
  • VS Code:按功能区域分组、对破坏性变更提供明确的迁移指引
  • Next.js:在 patch 版本中也能把修复描述得清晰有用,不滥用“improved performance”

这三个示例放在一起,向 Claude 传递了一个明确的信号:changelog 可以既简洁又有信息量,既专业又易读。我观察到,有示例和没有示例的情况下,生成文本的“废话率”(“提升了用户体验”“优化了系统性能”这类空洞表述的占比)从约 25% 降到了约 8%。

使用 claude code 自动化生成 changelog 与 commit 信息

5.5 第四步:集成到发布流程

最终的脚本整合为一个可执行文件 scripts/generate-changelog.sh

#!/bin/bash
set -e

配置

LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")

NEW_VERSION=$1

PROJECT_CONTEXT=$2

if [ -z "$NEW_VERSION" ]; then

echo "用法: ./generate-changelog.sh <新版本号> [项目上下文]"

exit 1

fi

echo "📋 正在提取 $LAST_TAG 到 HEAD 的 commit 记录..."

COMMITS=$(git log $LAST_TAG..HEAD --pretty=format:"%H|||%an|||%ad|||%s|||%b" --date=iso --first-parent)

echo "🤖 阶段一:结构化提取变更..."

python3 scripts/extract_changes.py "$COMMITS" "$PROJECT_CONTEXT" > /tmp/changes_raw.json

echo "🔍 请审核 /tmp/changes_raw.json,删除不应出现在 changelog 中的条目"

echo "审核完成后按回车继续..."

read

echo "✍️  阶段二:生成 changelog 文本..."

CHANGELOG=$(python3 scripts/generate_changelog.py /tmp/changes_raw.json "$NEW_VERSION")

echo "$CHANGELOG"

echo ""

echo "---"

echo "以上是生成的 changelog 草稿。请审核后手动更新 CHANGELOG.md。"

实际使用时,我会在准备发布时运行:

./scripts/generate-changelog.sh v2.4.0 "ShopAdmin 电商后台,本次聚焦大促前的性能优化和批量操作体验改进"
运行后脚本会在 /tmp/changes_raw.json 处停下来,给我一个审核机会。这一步通常不超过 10 分钟,我只需要删除那些明显不该出现的条目(比如“升级了 eslint 版本”),不需要手动写任何内容。审核通过后,脚本生成完整的 changelog 文本。

6 第五步:持续验证(防止脚本腐化)
如前面提到的,只在发布时运行脚本最大的风险是“发布日脚本挂了”。我的解决方案是在 CI 里加一个定时 dry-run:

.github/workflows/changelog-dry-run.yml

name: Changelog Generation Dry Run

on:

schedule:

cron: '0 2 * * 1'  # 每周一凌晨 2 点

push:

branches: [main]

jobs:

dry-run:

runs-on: ubuntu-latest

steps:

uses: actions/checkout@v4

with:

fetch-depth: 0

name: Setup Python

uses: actions/setup-python@v5

with:

python-version: '3.11'

name: Install dependencies

run: pip install anthropic

name: Dry run changelog generation

env:

ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}

run: |

python3 scripts/extract_changes.py "$(git log -50 --pretty=format:'%H|||%an|||%ad|||%s' --date=iso --first-parent)" "Dry run test" > /dev/null

echo "✅ Changelog 生成脚本运行正常"

这样做有两个好处:一是脚本如果有问题,会在周一凌晨被发现,不会拖到发布日;二是 dry-run 本身不做任何修改,零风险。

六、成本分析:这条流水线到底花多少钱

每次聊自动化方案,成本都是跳不过去的话题。我把过去五个月的实际消耗做了统计。

使用 claude code 自动化生成 changelog 与 commit 信息

用的是 Claude Sonnet 4 模型。为什么不用更便宜的 Haiku?因为 changelog 生成这个任务对语言质量要求很高,中文表达的自然度、技术术语的准确使用、不同条目间风格的统一性,Sonnet 在这些维度上明显优于 Haiku,多花的几美分完全值得。如果项目本身是英文 changelog,Haiku 可能就够了,这是语言结构决定的差异。

五个月总花费不到 9 美元。 对比一下,一个中高级开发者手动维护 changelog,每次 release 前后至少要花 45-90 分钟在整理、归并和润色上。按国内一线城市开发者时薪换算,一次 release 的人工成本大约是 API 调用成本的 100-200 倍。

当然,这里没有计入我搭建和调试这套流程的初始投入。从头搭建到稳定运行,我大概花了 20 个小时,包括学习 Claude API、写脚本、调试 prompt、处理各种边缘情况。如果你直接参考这篇文章的方案,这个时间投入可以压缩到 3-5 小时。

七、不同项目类型的适配建议

不是所有项目都适合用完全相同的方案。以下是我在几个不同类型的项目中实践后的差异化建议。

7.1 开源项目(面向外部用户)

适合度:最高。 开源项目的 changelog 是用户判断“要不要升级”的核心依据,质量要求最高。

额外建议:

  • changelog 中应该为破坏性变更提供明确的迁移步骤,这不是可选项。Claude Code 可以从 commit 中提取迁移相关的信息,但最终的步骤需要人工验证。
  • 考虑在 changelog 中链接到具体的 issue 和 PR 编号,方便用户追溯。在 prompt 里添加“如果 commit message 中包含 #数字,请在描述中保留该引用”可以做到这一点。

7.2 内部工具 / 中台项目(面向内部团队)

适合度:中等偏高。 内部项目 changelog 的读者是有技术背景的同事,他们更关心“API 签名变没变”“配置项有没有新增”,对产品化的表达要求较低。

额外建议:

  • prompt 的风格示例应该换成更技术化的样本。我在一个内部中台项目里用的是 Kubernetes 的 changelog 风格,简短、精确、术语密集。
  • 可以跳过“用户价值翻译”这一步,直接基于阶段一的 JSON 生成按模块分组的纯技术 changelog。

7.3 企业交付项目(面向客户、需要合规审计)

适合度:高,但需要额外环节。 这类项目的 changelog 可能作为交付物的一部分被客户审查,甚至需要符合某些合规要求。

额外建议:

  • 在阶段一的结构化提取中,添加对“安全相关变更”和“数据相关变更”的特殊标记。这两个类别在合规审查中通常需要特别关注。
  • 生成的 changelog 应该保留完整的 commit hash 映射,以便审计时追溯。
  • 人工审核不能省。 即使 Claude 的准确率是 97%,对于合规场景来说,3% 的错误率仍然不可接受。AI 生成的 changelog 应该作为草稿,最终版本必须由负责人签字确认。

7.4 单体转向微服务过程中的项目(仓库多、版本杂)

这种情况比较特殊。一个组织可能有 20 个微服务仓库,每个仓库有自己的发布节奏和 changelog。让每个团队各自维护一套生成脚本是不现实的。

额外建议:

  • 把 changelog 生成脚本做成一个共享的 CI 模板(类似 GitHub Actions 的 reusable workflow 或 GitLab CI 的 include)。
  • 在模板层面统一 prompt 结构和风格示例,各服务只需提供自己的 project_context
  • 考虑在组织层面建一个 changelog 聚合页,从各服务的 CHANGELOG.md 自动汇总,形成全产品的 release notes。这个聚合页也可以用 Claude Code 来生成摘要。

使用 claude code 自动化生成 changelog 与 commit 信息

八、已知局限与应对策略

不说局限的技术文章是耍流氓。以下是这套方案目前已知的问题,以及我的应对方式。

局限一:对非英语 commit message 的归并能力较弱

我的团队是中文技术团队,commit message 中英混杂是常态。Claude Code 在处理纯英文或纯中文的 commit 时表现都很好,但当 50 条 commit 中有 15 条中文、20 条英文、15 条中英混合时,归并的准确性会下降,它可能把描述同一个功能的中文 commit 和英文 commit 识别为两个独立的变更。

应对策略: 在阶段一的 prompt 中明确告知“commit message 可能使用中英两种语言,请在归并时考虑语义相似性而非仅依赖文本匹配”。这个提示能将归并准确率从约 70% 提升到约 85%。

局限二:对长期没有 tag 的项目,初始提取的 commit 量可能超出 token 限制

如果你接手一个一年没打 tag 的项目,期间可能有 500+ 条 commit。直接把 500 条扔给 Claude 是不现实的,即使是 200K 上下文的 Sonnet 4,输入过大的 commit 历史也会影响输出质量。

应对策略: 实现一个分段处理逻辑。如果 commit 数量超过阈值(我设的是 150),先按时间将 commit 切分成多个批次,每个批次独立调用阶段一,最后合并 JSON 结果再统一调用阶段二。分段处理对归并准确性有一定影响,跨批次的关联 commit 可能被重复记录,所以在合并阶段需要做一次去重。

def process_large_history(commits: list, batch_size: int = 150) -> dict:
"""分批处理大量 commit,合并后去重"""

all_changes = []

for i in range(0, len(commits), batch_size):

batch = commits[i:i+batch_size]

batch_text = "\n".join(batch)

batch_changes = extract_changes(batch_text, project_context)

all_changes.extend(batch_changes)

基于 related_commits 去重

return deduplicate_changes(all_changes)

局限三:对项目特定术语的理解有时不准

如果一个项目有自己的专有名词或缩写(比如内部给某个系统起的代号),Claude Code 可能误读这些术语的含义。比如我合作过的一个团队把他们的消息中间件叫做“灯塔”,Claude 第一次处理时把它理解成了监控告警系统。

应对策略:project_context 中显式列出项目专有术语及其含义。这不是“一次性配置完就没事了”,随着项目演进,术语表需要更新。我在项目文档里维护了一个 GLOSSARY.mdgenerate-changelog.sh 会自动读取它并注入到 prompt 的 context 里。

九、和现有工具的对比:为什么不用 Changesets / Release Please / Git Cliff

关于 changelog 自动化的工具,市面上已经有了不少选择。为什么还要自己基于 Claude Code 造轮子?我把主流方案和 Claude Code 方案做了个对比。

维度 Changesets Release Please Git Cliff Claude Code 方案
对 commit 规范的依赖 不依赖 commit 格式,但有独立的 changeset 文件要求 强依赖 Conventional Commits 依赖 Conventional Commits 不依赖任何 commit 规范
内容质量 由开发者手动编写 changeset 机械拼接 commit 描述 模板化拼接 AI 归纳 + 用户化表达
对开发者的侵入性 中等(每次 PR 需要创建 changeset 文件) 极低(只在 release 时触发)
学习成本 需要团队学习 changeset 工作流 需要团队遵守 commit 规范 需要配置模板 维护者配置一次,团队无需学习
中文支持 取决于开发者自己的书写 无特殊优化 无特殊优化 原生支持高质量中文输出
破坏性变更的迁移指引 需要手动编写 可从 commit 中自动提取并组织

Changesets 是一个很好的思路,它承认 commit message 不适合直接转化为 changelog 条目,因此引入了独立的“changeset 文件”概念。但它的代价是增加了每个 PR 的额外步骤。在一个已经要求 PR 模板、代码审查、CI 通过的流程上再加一个“请创建 changeset 文件”,推行的阻力不小。

Release Please 和 Git Cliff 走的是“严格执行规范,然后自动拼接”的路线。这条路的问题我前面已经讲过了:规范化的 commit message 本质上仍是技术记录,不是产品文档。 把 50 条规范的 commit 拼在一起,出来的东西依然是 commit 列表,不是 changelog。

使用 claude code 自动化生成 changelog 与 commit 信息

Claude Code 方案的核心优势在于零团队推行成本。开发者不需要改变任何习惯,不需要学习新规范,不需要在 PR 里多做一件事。流水线在 release 阶段静默运行,输出需要维护者审核,但不消耗其他任何人的注意力。

十、对未来的判断:AI 辅助的发布工程会走向哪里

五个月的实践让我对一件事非常有信心:AI 在发布工程中的角色,不会是替代人做决策,而是把人从“表述”的认知负荷中解放出来。 Changelog 是最典型的场景,决策(这个变更该不该写进 changelog?)仍然需要人的判断,但表述(怎么写才能让用户看懂?)完全可以交给 AI。

我预测在未来 12-18 个月内,会出现以下变化:

  1. 主流代码托管平台(GitHub、GitLab)将内置 AI 驱动的 release notes 生成功能。 这不是预测,GitHub 已经在 Preview 阶段测试基于 Copilot 的 release notes 生成了。但当前版本还很粗糙,基本是 commit 列表的摘要,缺乏本文强调的“翻译”和“归并”能力。
  2. Changelog 的形态会从“版本说明”演化为“变更叙事”。 随着 AI 生成质量的提升,changelog 不再是一堆要点的堆砌,而是以用户视角组织的、有逻辑顺序的变更故事。这对于大型版本的发布尤其有价值。
  3. 发布工程师的角色会从“写文档”转变为“审核 AI 输出”。 这已经在发生了。我的 changelog 工作流从“打开编辑器,写一小时”变成了“审核 AI 输出,改 10 分钟”。效率提升不是 2 倍,是 6 倍以上。更重要的是,我审核时的心态和写作时完全不同,写作时我会焦虑“有没有遗漏重要变更”,审核时我只需要检查“AI 有没有写错什么”。后者的认知负荷低得多。
  4. 多语言 changelog 将成为标配而不是奢侈配置。 目前大多数项目只维护一种语言的 changelog(通常是英文或中文)。但 Claude Code 本身是多语言的,同样的结构化变更清单,可以分别生成英文、中文、日文等多个版本的 changelog,成本几乎只是多次 API 调用的问题。

总结与下一步行动

这篇文章的核心观点可以用三句话概括:

第一,把 AI 放在 changelog 生成阶段,而不是 commit 生成阶段。 批处理胜过实时处理,归纳加表达胜过端到端生成,不改开发者习惯胜过强制推行规范。

第二,changelog 自动化的真正价值不是“省时间”,而是“降低认知负荷”。 手动维护 changelog 的痛苦不是打字累,而是每次都要在“代码思维”和“文档思维”之间切换。AI 承担了切换的中间环节,人只需要在关键节点做决策。

第三,用示例驱动,别用规则驱动。 给 Claude Code 三个好的 changelog 示例,比给它十页的格式规范更有效。示例传递的是“好是什么样”,规则传递的是“应该怎么样”,前者对模型行为的影响远大于后者。

如果你想立刻开始尝试,这是最小可行步骤:

  1. 选一个你正在维护的、有至少 20 条 commit 的项目。
  2. 复制本文 5.3 和 5.4 中的 prompt 模板,填入你的项目信息。
  3. 手动跑一次阶段一,看 Claude 提取的变更清单是否准确。 这一步不需要写任何代码,直接在 Claude Code 的对话界面或 API Playground 里试。
  4. 如果准确度满意,再花一个小时把脚本封装起来。 本文 5.5 的脚本可以直接修改使用。
  5. 下一次发布时用生成的 changelog 作为草稿,人工审核后发布。

在第一个项目上跑通后,你可以考虑把同样的逻辑复制到其他项目,或者抽象成一个共享的 CI 模板。我在第五个月的时候已经把三个项目的 changelog 维护工作交给了这条流水线,每个月踩一次坑的频率从“每次发布必踩”变成了“偶尔”。

工程化的本质,是把重复的认知劳动变成可靠的自动化流程。 Changelog 是认知劳动密集但规则明确的典型场景,它需要的不是创造力(那是写代码时用的),而是耐心、细心和一致性。而这些,恰恰是 AI 擅长的。

常见问题解答(FAQ)

1. Claude Code自动生成commit message会不会导致commit信息过于泛化或失去人工审核的必要性?

我担心AI生成的commit message虽然规范但没灵魂,团队review时反而需要额外解读,效率不升反降。

从实际部署经验看,关键在于prompt设计和人工把关。我踩过的坑是把所有权限都交给AI,结果出现“Fixed minor issues”这样的模糊信息。

后来我们限制AI只需生成格式化的title(如feat(api): add user authentication),而详细的body留空或提示用户手动补充关键决策理由。通过git hooks在提交前弹出生成的message让开发者确认,既保证格式统一又不丧失人性化。

我们团队两月实践下来,commit规范率从30%提升到95%,但每个人的commit都经过了人工快速扫读,平均每条多花5秒,但后续查找历史节省了大量时间。

2. Claude Code生成的commit message能否与团队的Conventional Commits规范完全兼容?需要额外配置吗?

我们已经推行了Conventional Commits,但工具多、习惯难改,想知道接入AI是否要推翻现有规范。

完全可以兼容,甚至能强化执行。我们实际配置时,在prompt中明确要求输出格式为 <type>(<scope>): <description> 并且限定type只允许 feat/fix/docs/refactor 等预设项。

Claude Code会严格遵循,但偶尔会错误地将非功能性变更标记为feat。解决方案是在git hook中加一段校验脚本:如果type不在允许列表内,则拒绝提交并给出修改建议。这样AI充当了规范性辅助,而非最终决策者。

我们额外搭建了一个小脚本来解析AI生成的message,如果不符合规范自动调用openAPI修正。整体配置成本约半天,但之后无人工干预。

3. 使用Claude Code自动化生成Changelog,对于大型项目(上千次commit)是否可行?API调用次数和成本如何?

我们项目有3000+次提交,担心API调用次数爆炸、成本高,而且Changelog太长无用。

我亲自测试过5000+ commit的项目。关键策略是增量处理:不要每次全量读取所有历史,而是只读取上一个版本tag到当前HEAD之间的commit(通常几十到几百条)。

Claude Code API按token计费,以2025年定价约$0.15/1M tokens输入,$0.60/1M tokens输出。

一个中型版本(100条commit,每条平均80词)的diff文本大约8000 tokens,加上prompt和输出,一次Changelog生成成本约0.01美元。如果每月发版10次,成本可忽略。

但需要留意context window:Claude Code最大支持200K tokens,如果commit太多建议分批处理。我们实践发现,超过300条commit一次性输入容易遗漏细节,建议按功能模块分段生成再合并。

4. Claude Code自动化Git流程如何保证代码安全?把项目代码diff发给第三方API是否存在安全隐患?

公司有严格的数据安全政策,担心代码泄漏。

这一点必须重视。我推荐的方案是:1)使用Claude Code的本地CLI,在本地运行而非调用云端API(如果本地模型能满足)。Claude Code支持本地部署,但需要大显存GPU。

2)如果必须使用云端API,建议只发送commit message和简略的documentation diff,不发送核心业务逻辑代码。我们在git hook中做了过滤:只提取修改的文件路径、函数名和注释部分,去除具体实现代码。

3)与Anthropic签订Business Associate Agreement(BAA)或使用企业版以获得数据不用于训练的承诺。4)在CI/CD中使用带限流和审计的专用API key。经过以上措施,我们通过安全审计。实际成本增加约20%,但安全合规达标。

核心关键词

读者评论

顾清

把 AI 放在 changelog 阶段而不是 commit 阶段,这个判断太准了。我之前也试过在 pre-commit 里接 LLM,打断感真的很强,团队没几天就都跳过了 hook。用 commit history 來提炼反而容错率高,试了几次事实性错误确实少很多,而且不需要改大家提交习惯,落地阻力小太多。

程远

对于“commit message 是写给协作者的,changelog 是写给用户的”这一点很认同。我之前用 conventional commits 加工具自动拼出 changelog,结果就是一堆 feat/fix 列表,非技术用户完全看不懂。缺少从技术细节到用户价值的“翻译”,这个才是真痛点。

韩知行

我自己也维护几个开源项目,changelog 拖更的情况跟文章说的完全一致。印象最深的是上下文切换成本那段,发布越频繁越难跟上。现在用类似方法把 commit 分类和归并交给 LLM,我只做终审,认知负荷降了一档。

李卓

看到上下文切换需要 15-23 分钟的引用,很有共鸣。之前觉得忙到没空更新 changelog 是时间管理问题,其实本质是大脑在编码和写文档之间切换成本太高。把机械的筛选、归并甩给 Claude 之后,写 changelog 的心智负担确实小了很多。

王安宁

好奇实际 prompt 是怎么设计的,尤其是把多条 commit 合并成一条用户友好的描述时,怎么控制它不丢失关键变更又不啰嗦。还有 API 成本,处理 200 多个 commit 的 history 会不会很烧 token?希望后续能有更多工程细节分享。

文章版权归“万象方舟”www.vientianeark.cn所有。发布者:程, 沐沐,转载请注明出处:https://www.vientianeark.cn/p/599444/

温馨提示:文章由AI大模型生成,如有侵权,联系 mumuerchuan@gmail.com 删除。
(0)
用 claude code 辅助代码审查时如何避免过度依赖
上一篇 3分钟前
通过 claude code 学习框架源码的阅读路线设计
下一篇 3分钟前

相关推荐

  • 使用 claude code 编写区块链智能合约时的注意事项

    去年 11 月,我接到一个紧急电话。电话那头是一位 DeFi 协议的 CTO,声音里带着明显的慌乱。他们三天前刚刚部署了一个新的流动性池合约,代码是团队用 Claude Code 辅助生成的,逻辑看起来一切正常。但就在那个凌晨,合约被一个精心构造的闪电贷攻击击穿,损失了大约 23 万美元。事后复盘时,我们一行一行地排查代码,最终在一个看似普通的条件判断里找到了漏洞。Claude 生成的代码处理了正…

    29秒前
    000
  • 在原生 JavaScript 项目中使用 claude code 保持 ES 规范

    去年底我刚接手一个原生 JavaScript 老项目,三年前写的,没有任何框架,模块全是用 IIFE 包一包然后挂到 window 上。项目共 247 个 JS 文件,我随手抽了其中 30 个文件跑 ESLint,使用 airbnb-base 规则集,报错总数是 1,384 条,平均每个文件 46 个问题。那一刻我心里只有一个念头:如果引入 Claude Code,它写的代码会不会也变成这样?还是…

    1分钟前
    000
  • 用 claude code 生成 Web 组件的 Shadow DOM 实现

    用 claude code 生成 Web 组件的 Shadow DOM 实现 上个月的一个深夜,我刚合并完一个 PR,不到三十分钟,QA 就在群里发了一段视频,我们的用户中心页整片变成了天蓝色。所有文字都消失了,只剩下蓝茫茫的一片背景。根因排查花了将近四个小时,最终定位到一个同事在重构某个“可复用组件”时,不小心把 .container { background: #1890ff } 写进了全局样…

    1分钟前
    000
  • 为 claude code 配置自定义代码风格指南的完整方案

    我们团队在2024年第四季度做了一个内部统计:Claude Code接入项目的前两周,AI生成的代码有31%在Code Review阶段被标注“风格不一致”,其中17%直接导致合并请求被打回重做。更让人头疼的是,同一类风格问题反复出现,缩进、命名、import排序,每次都靠人肉纠正,每次纠正完下次AI又换一种写法。 有人会说:配置个ESLint不就解决了?问题在于,Linter是事后检查,Clau…

    2分钟前
    000
  • claude code 在 pair programming 虚拟环境中的协作模式

    我们团队在去年第四季度经历了一次触及灵魂的远程协作危机:一个原本只需要两人结对三小时就能完成的支付网关重构任务,因为沟通分歧、上下文丢失和频繁的屏幕共享卡顿,硬生生拖成了一天半的折磨。事后复盘,我们发现真正消耗时间的并不是代码本身,而是“等待对方理解我的意图”和“重新建立共同心智”这两个黑洞。恰在那时,Claude Code 开放了针对终端环境的深度集成,我们决定做一场为期两周的对照实验,看看这款…

    2分钟前
    000
站长微信
站长微信
分享本页
返回顶部