用 dev-分支名 不能真正锁定版本,仅指向分支最新提交;真正锁定需用 dev-分支名#commit-hash 格式,含斜杠分支名须 url 编码;推荐通过 repositories 声明 fork 并打 tag 或设 version 实现语义化稳定依赖。

用 dev-分支名 作为版本号能锁定分支,但不是“固定”
很多人以为写 "vendor/package": "dev-main" 就锁死了 main 分支——其实它只是告诉 Composer 去拉最新的 main 分支 HEAD,每次 composer update 都可能更新到新提交。这不是真正的“锁定”,只是“指向分支最新”。
- 真正锁定某次提交,得用
dev-分支名#commit-hash格式,比如"vendor/package": "dev-main#abc1234" - 如果分支名含斜杠(如
feature/login-flow),必须 URL 编码为feature%2Flogin-flow,否则 Composer 解析失败 - 使用
#后缀后,Composer 会把该包当作dist类型处理(即使源是 Git),跳过git clone,直接下载打包好的 zip
composer.json 里写 repositories 是更可控的方式
当你要长期维护一个 fork 或临时 patch 某个包时,硬编码 dev-xxx#hash 很难维护。这时应该显式声明 repositories,并把 version 设为稳定格式(如 1.2.3),再用 require 正常引用。
- 在
composer.json的repositories数组里加一条 typevcs的配置,url指向你的 fork 地址 -
require中仍写"vendor/package": "1.2.3",但前提是你的 fork 在对应 commit 上打了v1.2.3tag,或在composer.json里手动设了"version": "1.2.3" - 如果不打 tag,又想用语义化版本号,就得在 fork 的
composer.json里显式写"version": "1.2.3-patch1",且确保minimum-stability允许dev或stable匹配
运行 composer update 时,--with-dependencies 可能意外更新分支
当你只更新某个包(composer update vendor/package),它的子依赖若也用了 dev-xxx 写法,且没加 #hash,就会被连带更新到分支最新版——这是最隐蔽的“失控点”。
- 检查所有依赖是否都用了
#commit-hash,尤其是间接依赖(看composer show输出) - 执行
composer update前先跑composer update --dry-run,重点看哪些包的 commit hash 变了 - CI 环境中建议加
composer install --no-dev --prefer-dist --optimize-autoloader,避免因本地dev分支状态污染构建结果
Git 分支名变更或删除后,dev-xxx 会直接报错
Composer 不会自动 fallback 到其他分支,一旦你依赖的 dev-feature/x 被 rebase、force-push 或删掉,下次 composer install 就卡在 Could not find package vendor/package at version dev-feature/x。
- 上线前务必确认远程仓库中该分支存在且可访问(尤其私有 GitLab/Gitee)
- 如果分支只是重命名,需同步改
composer.json并提交,不能只改本地配置 - 比起分支名,用
tag或#commit-hash更可靠;分支只适合短期协作开发,不适合发布环境










