git merge 不会自动更新 changelog.md,需通过 husky + commitlint + standard-version 组合在 post-merge 钩子或 ci(如 github actions)中解析符合约定格式的提交来生成日志,关键在于提交规范、正确范围及命令调用。

git merge 时不会自动更新 CHANGELOG.md,必须靠规则驱动
Git 本身不提供合并时自动生成或追加日志的功能。所谓“自动更新”,本质是借力 CI 流程或本地钩子,在 merge(尤其是 main 或 release 分支)发生后,触发一个基于提交历史的解析动作。关键不是 merge 本身,而是 merge 后的 commit 是否符合约定格式、以及有没有工具监听这个节点。
用 husky + commitlint + standard-version 实现 merge 后自动补日志
这是目前最轻量且可落地的组合方案,适用于团队已开始规范提交但尚未接入完整发布流水线的场景:
-
husky在post-merge钩子中判断当前分支是否为main(或develop),再执行生成逻辑 -
commitlint确保所有被 merge 进来的 commit 都带feat/fix等前缀,否则standard-version无法分类 -
standard-version不直接响应 merge,但它能识别「从上一个 tag 到当前 HEAD」之间的所有约定式提交,并追加到CHANGELOG.md
示例 .husky/post-merge 脚本:
#!/bin/sh branch=$(git rev-parse --abbrev-ref HEAD) if [ "$branch" = "main" ]; then npx standard-version --skip.commit --skip.tag --skip.push fi
注意:--skip.commit 和 --skip.tag 是为了只生成日志内容,不改动版本号或打 tag —— 因为 merge 本身已经完成,你只需要日志增量。
CI 中基于 merge commit 触发 changelog 更新(GitHub Actions)
比本地钩子更可靠,尤其适合多开发者协作项目。核心是监听 pull_request 的 closed 事件,并确认其 merged 为 true:
- GitHub 默认不会把 PR 合并提交(merge commit)当作常规提交解析 —— 它的 message 是
Merge pull request #123 from feat/login,不含feat前缀 - 必须配置 PR 模板强制要求描述字段填写变更类型,或使用
squash and merge方式,让最终提交 message 继承 squashed commits 的首行 - 推荐在 workflow 中加一步:先 fetch 所有 commits(
git log origin/main..HEAD --no-merges),再交给conventional-changelog处理
关键命令片段:
git fetch --prune --unshallow || git fetch --prune origin npx conventional-changelog -p angular -i CHANGELOG.md -s \ --commit-path . \ --from $(git describe --tags --abbrev=0 2>/dev/null || echo "HEAD~100") \ --to HEAD
这里 --from 用 git describe 动态取最近 tag,避免硬编码;--no-merges 必须加,否则日志里全是 “Merge branch…”。
容易忽略的三个断裂点
很多团队卡在这几步导致“看似配置好了,但日志没更新”:
- merge 后没
git push:本地post-merge生成了日志,但没人git add && git commit && git push,日志只存在本地 - CI 中未 checkout full history:
actions/checkout@v4默认只 fetch depth=1,git log只能看到最新一次提交,必须加fetch-depth: 0 - changelog 工具读取的是 commit message 的第一行(subject),不是 body 或 footer —— 所以
feat(auth): add SSO✅,add SSO (feat/auth)❌
真正起作用的永远不是“merge 这个动作”,而是 merge 带来的那一组符合约定的提交,以及你是否在正确的时间、用正确的范围、调用了正确的解析命令。











