Composer不创建分支版本,只匹配Git远程真实分支(如dev-main需对应远程main分支,大小写敏感),branch-alias在Composer 2.0+已失效,安装后锁定commit hash而非分支,私有包须显式配置repositories。

Composer 不创建分支版本,它只按你写的约束去匹配 Git 分支或 tag —— 真正的“版本”由 Git 仓库状态决定,不是 Composer 生成的。
dev-分支名必须和 Git 远程分支完全一致
写 dev-main 却报 Could not find a version of package xxx?大概率是远程仓库根本没有 main 分支,或者实际叫 master、develop 甚至 Main(大小写敏感)。
- 用
git ls-remote --heads https://github.com/vendor/name.git直接查远程真实分支名 - 含斜杠的分支(如
feature/login)必须写成dev-feature/login,不能省略dev-或改成下划线 - 私有仓库用 SSH 地址(如
git@gitlab.example.com:acme/utils.git)时,确保运行composer install的机器已配好对应 SSH key
branch-alias 在 Composer 2.0+ 已彻底失效
如果你还在 extra.branch-alias 里写 "dev-main": "1.0.x-dev",它不会报错,但也不会起任何作用 —— Composer 2.x 直接跳过解析。
- 下游项目写
"acme/utils": "^1.0"依然匹配不到,因为 alias 不再参与版本解析 - 替代方案只有两个:
"version": "1.0.x-dev"(写在包自己的composer.json里),或打 Git tag(如v1.0.0-beta.1) -
version字段必须带-dev后缀,否则会被当作稳定版,触发冲突
安装 dev 分支后锁定的是 commit hash,不是分支本身
composer require vendor/name:dev-main 后,composer.lock 记录的是当前 HEAD 的完整 commit hash,比如 "reference": "a1b2c3d4..."。这不是 bug,是设计使然。
- 后续该分支
git push --force覆盖了这个 commit,下次composer install就会失败,报Failed to download... - 想让每次
install都拉最新提交?得加--prefer-source,且每次更新都需手动进vendor/name执行git pull,或跑composer update vendor/name - 生产环境长期依赖
dev-main是高风险行为,CI 构建可能随时崩掉
私有包没注册 Packagist,必须显式声明 repositories
直接 composer require acme/internal:dev-main 失败?不是 Composer 问题,是你没告诉它“去哪找这个包”。
- 在项目根目录
composer.json的repositories段加 vcs 源:{"type": "vcs", "url": "https://gitlab.example.com/acme/internal.git"} -
url必须能被机器直连(HTTPS 可能要配 token,SSH 要配 key) - Git 仓库根目录必须有
composer.json,且其中name字段必须和require里写的完全一致(包括大小写)
最常被忽略的一点:很多人花半天调试 branch-alias 为什么不生效,却没意识到 Composer 2.x 已经把它整个删掉了 —— 查一眼自己用的 Composer 版本(composer --version),比改配置快得多。











