Git提交记录不能直接生成Composer可用变更日志,因Composer不读取Git日志或composer.json历史diff;需脚本提取composer.json/composer.lock修改提交,用jq比对require字段变化,生成CHANGELOG.md片段,且须人工校验确保准确。

Git 提交记录本身不能直接生成 Composer 可用的变更日志——因为 Composer 不读取 Git 日志,也不解析 composer.json 的历史 diff。所谓“自动更新”,实际是靠脚本把 Git 提交中与依赖相关的改动(如 composer.json、composer.lock 修改)提取出来,再格式化为人类可读的 CHANGELOG.md 片段。
怎么从 Git 提交里识别出真正的依赖变更
仅靠 git log --oneline 看不到哪些提交动了依赖。必须结合文件路径过滤和内容比对:
- 先用
git log --pretty=format:"%h %s" --name-only -m --follow -- composer.json composer.lock找出所有修改过这两个文件的提交 - 再对每个提交,用
git show <commit>:composer.json和git show <commit>^:composer.json做 JSON diff(推荐jq或diff -u),只保留require、require-dev、version字段的变化 - 忽略仅改注释、空格、或仅更新
composer.lock但没动composer.json的提交(这类通常是composer install触发的,不算“语义变更”)
为什么不能直接用 conventional commits 规范来标记依赖变更
Conventional Commits(如 chore(deps): bump laravel/framework from 10.10 to 10.11)看着干净,但实际落地有硬伤:
- 没人强制每次
composer update都写这种格式,团队执行率低 - CI 脚本无法验证 commit message 是否准确——比如你写了
bump foo/bar,但实际composer.json里根本没这个包 - 版本号可能被手动编辑(如从
^2.3改成^2.4),而 commit message 没同步更新,导致日志错乱
更可靠的做法是:让脚本自己从 composer.json 的 diff 中提取包名和版本变化,再拼成标准句式,不依赖人写对 message。
使用四维度框架评估任意 GitLab MR 或 GitHub PR 的复杂度:规模(20%),认知负荷(30%),审查工作量(30%),风险/影响(20%)...
如何用 shell + jq 快速生成最小可用变更日志片段
以下脚本只处理最近一次涉及依赖的提交,输出 Markdown 格式条目,适合集成进 CI 后追加到 CHANGELOG.md:
#!/bin/bash
COMMIT=$(git log -n1 --pretty=%H --name-only -m --follow -- composer.json composer.lock 2>/dev/null)
if [ -z "$COMMIT" ]; then exit 0; fi
<h1>提取上一版和当前版的 require/require-dev</h1><p>OLD_JSON=$(git show ${COMMIT}^:composer.json 2>/dev/null | jq -r '.require, .["require-dev"] | keys[]?')
NEW_JSON=$(git show ${COMMIT}:composer.json 2>/dev/null | jq -r '.require, .["require-dev"] | keys[]?')</p><h1>找出新增/升级/移除的包(简化版,生产环境建议用更严谨的 diff 工具)</h1><p>ADDED=$(comm -13 <(echo "$OLD_JSON" | sort) <(echo "$NEW_JSON" | sort) | sed 's/^/- /')
REMOVED=$(comm -23 <(echo "$OLD_JSON" | sort) <(echo "$NEW_JSON" | sort) | sed 's/^/- /')</p><p>if [ -n "$ADDED$REMOVED" ]; then
echo "### Dependencies"
echo "$ADDED"
echo "$REMOVED"
echo ""
fi</p>注意:jq 必须已安装;comm 要求输入已排序;该脚本不处理版本号变化细节(如从 1.2.3 到 1.2.4),只做增删判断——如果需要精确版本差,得用 jq 分别提取两个版本的 value 并比对。
最容易被忽略的兼容性陷阱
生成的日志若用于发布流程(如 GitHub Releases),要注意三件事:
-
composer.lock的变更可能跨多个提交(例如先改composer.json,再composer update提交 lock),脚本必须能合并识别,否则漏掉关键升级 - 某些私有包使用
vcs或package类型仓库,其版本字段可能是dev-main或1.0.x-dev,直接字符串比对会误判为“未变” - PHP 版本约束(
config.platform.php)也算依赖环境变更,但不在require字段里——如果脚本只盯require,就会漏掉这个重要兼容性提示
真正稳定的方案不是追求“全自动”,而是把脚本做成“半自动校验器”:它列出所有可疑变更,人工确认后一键插入日志——省时间,不省责任。

















