composer update 会更新 composer.lock,而 composer install 不会;--lock 参数仅重写 lock 文件结构而不升级包,--dry-run 则完全不修改 lock 文件。

composer update 不更新 composer.lock?先确认你真在执行对的命令
默认情况下,composer install 只按 composer.lock 安装,完全不碰 composer.json;而 composer update 才会重新解析依赖、升级版本、并重写 composer.lock。如果你改了 composer.json 但 composer install 后 lock 文件没变,不是“没生效”,是它压根就不该变。
想强制重生成 lock 文件,用 composer update --lock
这个参数告诉 Composer:别管 composer.json 有没有改,也别升级包,只把当前 composer.lock 按照现有 composer.json 的约束“重新格式化”“重新排序”“补全缺失字段”。常见于以下场景:
- 团队协作中 lock 文件格式不一致(比如有人用了新版 Composer,有人用了旧版)
- 手动编辑过
composer.json但漏删了某些字段,导致 lock 文件校验失败 - CI 环境要求 lock 文件必须由当前 Composer 版本生成,避免隐式兼容问题
注意:--lock 不会改变任何包的实际版本号,也不会触发下载或安装,只是“刷新 lock 结构”。
composer update 和 composer update --dry-run 的关键区别
很多人以为加 --dry-run 是“安全更新”,其实它只是模拟计算过程,不会写入 lock 文件——也就是说,它根本不会生成/更新 composer.lock。真正要更新 lock,必须去掉 --dry-run,或者明确加 --lock。
-
composer update→ 解析依赖、升级包、写新 lock -
composer update --dry-run→ 只打印将要做的事,lock 文件纹丝不动 -
composer update --lock→ 不升级包,只重写 lock(等价于composer update --lock --no-install)
如果本地有未提交的 composer.json 修改,composer update 会基于它计算,而 composer update --lock 同样会基于当前文件内容重写 lock,所以改完 json 后直接跑这个最稳妥。
容易被忽略的坑:Composer 版本差异导致 lock 格式不兼容
Composer 2.x 生成的 lock 文件包含 content-hash 和更细粒度的平台信息,老版本(如 1.10)读取时可能报错 The lock file does not contain require-dev information 或直接拒绝加载。这不是 lock “坏了”,是版本越界。
- 团队共用 lock 文件时,所有人应尽量使用相同大版本的 Composer(推荐统一用 2.x)
- CI 脚本里别写死
composer self-update,它可能升到不稳定分支;建议锁定版本,例如composer self-update 2.5.8 - 如果必须降级使用 lock,不要手改,而是用对应版本的 Composer 执行一次
composer update --lock
lock 文件本质是“确定性快照”,它的价值不在内容多好看,而在所有环境能复现同一套依赖树——格式差异只是副产品,别让它干扰判断。










