composer install 从不更新 composer.lock,它只按 lock 文件精确还原 vendor 目录;改 composer.json 后必须运行 composer update --lock(同步元信息)或 composer update vendor/package(升级依赖)才能更新 lock。

为什么 composer install 从不更新 composer.lock
composer install 的唯一职责是「还原」——按当前 composer.lock 中记录的精确版本、哈希、路径,把 vendor/ 目录恢复成一模一样的状态。它压根不看 composer.json 里新加了什么包、改了什么约束,也绝不会动 lock 文件一个字节。
- 你改了
composer.json的require,但没运行composer update或composer update --lock→install仍装旧版本,且提示 “Nothing to install or update” - CI/CD 流水线里靠它保证每次构建依赖完全一致;生产部署时靠它回滚到某 commit 对应的可信快照
- 如果
lock文件缺失,install会退化为update并自动生成新lock,这属于意外行为,务必提前检查
composer update --lock 到底改了什么?
它只重算并更新 composer.lock 文件顶部的 content-hash 字段,其他所有包版本、子依赖树、dist URL、校验哈希全部保持原样。本质是「同步元信息」,不是「升级依赖」。
- 适用场景:改了
composer.json的description、autoload、scripts或config.platform.php等非依赖字段后,避免 CI 报 “Your lock file is out of sync” - 注意:若你切换了镜像源(比如从 packagist.org 换成私有仓库),同一包的 dist URL 可能不同,此时
--lock也会更新对应字段,不只是哈希 - 它不会解决任何依赖冲突,也不触发包下载或重装,
vendor/目录完全不动
想更新某个包?别用 --lock,用 composer update vendor/package
composer update --lock 不能升级任何包;真正改变 lock 中某项版本的,只有带包名的 update 命令。
-
composer update monolog/monolog:重新解析该包及其子依赖,按composer.json当前约束拉取最新兼容版本,并刷新lock - 加
--with-dependencies会连带更新它的直接依赖(慎用,易引发连锁变更) - 加
-v可看到实际被更新的包列表,确认是否误触了不该动的依赖 - 如果
composer.json里写的是"^2.0",而当前锁的是2.9.1,新版本2.10.0兼容,update就会升上去;但若约束仍是"^2.0"且已锁在2.10.0,就不会动
常见错觉:“我改了 composer.json,为什么 install 不生效?”
这不是 bug,是设计使然。Composer 明确区分「声明」(composer.json)和「快照」(composer.lock)两个层面。改了声明却不更新快照,install 就只会忠实地还原旧快照。
- 现象:
install提示 “Lock file is not up to date”,但没报错、也没装新包 - 原因:你新增了
require,或改了已有包的版本约束,但忘了运行composer update --lock(仅同步)或composer update vendor/name(真升级) - 风险操作:删
composer.lock+rm -rf vendor+composer install→ 它会自动update并生成新lock,但所有依赖都会按最新兼容版重算,极易引入破坏性变更
最常被忽略的一点:修改 composer.json 后,哪怕只是加了个空格,也要手动同步 lock 文件,否则团队协作或 CI 构建就可能因哈希不匹配失败——这个细节没有警告,却直接影响交付稳定性。










