Composer平滑迭代需确保Git tag(vX.Y.Z轻量tag)、composer.json(无version字段)、Packagist同步、CI执行四者严丝合缝;任一环节出错,下游将无法安装新版本。

Composer 本身不生成版本,也不打 Git tag;所谓“平滑迭代”,本质是让 Git tag、composer.json 声明、Packagist 同步、CI 执行这四者严丝合缝。错一个环节,下游就装不到新版本。
Git tag 必须用 vX.Y.Z 格式,且是轻量 tag
Packagist 和 Composer 只识别形如 v1.2.3 的轻量 tag(git tag v1.2.3),其他格式一律跳过:
-
1.2.3(无v前缀)→ 被当 dev 别名,composer require默认不拉 -
v1.2.3-beta或v1.2.3+build.1→ 不符合 SemVer 主干格式,被忽略 -
git tag -a v1.2.3 -m "release"(带注解)→ 某些旧版 Packagist 解析失败,建议统一用轻量 tag - 本地打了 tag 但没
git push origin v1.2.3→ 远端不可见,Packagist 同步不了
composer.json 中不要写死 version 字段
写 "version": "v1.2.3" 是最常见误操作,它会覆盖 Git tag 解析逻辑,导致 Packagist 拒绝同步或下游安装失败:
- 开发时:删掉
version字段,或留空,或设为"dev-main"(仅用于本地测试) - 发布前:确保
composer.json中无version键,靠 tag 驱动版本识别 - 私有包同理:若
repositories类型为vcs,也必须删掉version,否则 Composer 优先读它 - 验证方式:
composer show vendor/name --all输出中应明确列出v1.2.3且标注为stable
CI 脚本里打 tag 前必须校验是否已存在
GitHub Actions 或 GitLab CI 中自动打 tag 时,同一版本号重复触发会导致 fatal: tag 'v1.2.3' already exists 报错中断:
- 用
git ls-remote --tags origin | grep -q "v${VERSION}$"检查远端是否存在该 tag - 别用
jq '.version'提取版本 —— Windows/BusyBox 环境可能没jq,改用 PHP 一行:php -r "echo json_decode(file_get_contents('composer.json'), true)['version'] ?? '';" -
actions/checkout@v4默认不 fetch tag 历史,务必加fetch-depth: 0,否则git ls-remote查不到已有 tag - 打完 tag 后必须执行
git push origin --tags(不是git push),否则远端收不到
Packagist 同步失败的三个关键检查点
明明推了 v1.2.3,但 composer require 还是报 Could not find package,大概率卡在这三处:
- Packagist 仓库设置页未勾选 Automatically update the package on new commits?(常被忽略)
- GitHub/GitLab webhook 没配或配错:GitHub 要勾选 Tag push events,endpoint 是
https://packagist.org/api/github - 私有 GitLab 仓库需手动配置 webhook,Packagist 不主动轮询;且 payload 中
repository.url必须和 Packagist 上登记的 source URL 完全一致(含https://或git@前缀) - 验证是否生效:运行
curl -s "https://repo.packagist.org/p/vendor/name.json" | grep '"time"',看最新版本时间戳是否更新
真正容易被忽略的是:tag 推上去了,webhook 也发了,但 Packagist 收到后因 composer.json 里残留 version 字段而静默拒绝同步——它不会报错,只是跳过。所以每次发布前,先 git checkout main && git grep -n version composer.json 确认字段已清空。











