composer对changelog.md完全透明,只认composer.json的version字段和git tag;三者必须严格一致(如v2.3.1、"version": "2.3.1"、## [2.3.1]),否则日志失效。

CHANGELOG.md 对 Composer 完全透明,别指望它自动读取
Composer 从不解析、校验或使用 CHANGELOG.md —— 它只认 composer.json 里的 version 字段,或 Git 仓库的 tag。你花一小时写得再漂亮的日志,只要没打对应 tag,composer require vendor/package:^2.3 就不会“看到”它。
常见错误现象:composer update 后功能没生效,翻 CHANGELOG.md 却发现条目模糊(如“优化初始化逻辑”),根本无法判断是否包含自己需要的修复;或者把日志当 API 文档用,漏看了实际代码里 Config::getRequired() 是新增方法而非修改旧方法。
真正起作用的只有三件事:
- Git tag 必须存在且命名严格匹配(
v2.3.0,不是2.3.0或release/2.3.0) -
composer.json中的"version"字段必须与 tag 完全一致("version": "2.3.0",不能带v前缀) -
CHANGELOG.md的标题段落必须是## [2.3.0] - 2026-08-25,日期填发布当天,不是 commit 日
私有仓库中 CHANGELOG 必须和 Packagist 同步逻辑对齐
私有 Git 仓库("type": "vcs")不提供 packages.json,Composer 是靠扫描 tag 和分支动态生成可用版本的。这意味着:如果你在私有仓库打了 v2.3.0 tag,但 CHANGELOG.md 里写的是 ## [2.3.1],那使用者通过 composer show vendor/package 看到的版本是 2.3.0,却找不到对应日志段落——因为日志和 tag 脱节了。
使用场景:你刚合并 PR #88(修复 MySQL 连接池复用失效),准备发版。操作必须按顺序来:
- 先改
composer.json的version为"2.3.1" - 提交并 push 到主干
- 打 Git tag:
git tag v2.3.1 && git push origin v2.3.1 - 最后更新
CHANGELOG.md,在## [2.3.1] - YYYY-MM-DD下加一行:Fixed MySQL connection pool reuse failure (#88)
跳过任意一步,日志就失去锚点。尤其注意:私有仓库没有 Packagist 的自动同步钩子,tag 和日志全靠人工对齐。
别用模糊动词,每条变更必须可验证、可回溯
“提升稳定性”“增强兼容性”这类描述在私有仓库里毫无意义——你没法 grep、没法写自动化检查、更没法向同事证明“这个 bug 确实修了”。日志条目必须指向具体行为变化,且能被测试或运行时观测到。
正确写法示例:
Added HttpClient::withTimeout(int $ms) method for per-request timeout controlFixed crash when parsing YAML with nested empty arrays (#72)Deprecated Config::get() in favor of Config::getNullable(), will be removed in v3.0
错误写法(直接删掉):
-
Updated dependencies(谁更新?更新了什么?) -
Improved performance(快了多少?压测数据在哪?) -
Fixed some bugs(哪些?怎么复现?)
每条末尾必须带 (#PR) 或 (issue #N),方便快速跳转上下文。私有仓库通常没公开 issue tracker,那就确保 PR 描述本身写清问题现象、复现步骤和修复原理。
私有包的 CHANGELOG 不该只放 GitHub/GitLab 上
很多团队把 CHANGELOG.md 仅放在私有 Git 仓库根目录,结果新成员第一次 composer require 后,连日志在哪都不知道——composer show 不显示路径,vendor/ 里又没存原始文件,只能靠记忆或搜索。
实操建议:
- 在包的
composer.json中明确写"support": {"docs": "https://internal-docs.myorg.dev/packages/myapp-sdk/changelog"},指向内网文档页 - CI 流水线在发布成功后,自动生成 HTML 版本并推送到内部静态站点(比如用
gh-md-toc提取目录,marked渲染) - 如果必须用纯文本,确保
CHANGELOG.md在每个 tag 提交时都存在于仓库根目录——不要放在docs/子目录下,否则git log v2.2.0..v2.3.0 --oneline CHANGELOG.md会查不到修改
最常被忽略的一点:私有仓库的访问权限往往比主项目更严。有人能 composer install,却没权限 git clone 查日志。所以日志入口必须独立于源码访问控制,否则它就只是个摆设。











