真正更新 composer.lock 的操作只有两类:composer update 会无视现有 lock,重新解析 composer.json 并覆盖写入新锁文件;composer update --lock-only(2.2+)则仅刷新 content-hash、格式和元数据,不升级包。

composer.lock 文件只在明确需要变更依赖快照时才更新,不是每次改 composer.json 都要动它,也不是每次 composer install 都会重写它——关键看操作意图和命令语义。
哪些操作会真正更新 composer.lock?
只有两类命令会写入新内容到 composer.lock:
-
composer update:无视现有composer.lock,重新解析composer.json中所有require/require-dev的版本约束,计算最新兼容组合,覆盖写入新锁文件(含新哈希、新 dist sha256、新依赖树) -
composer update --lock-only(Composer 2.2+):不升级包,只校验当前vendor/是否仍满足composer.json全部约束,仅刷新content-hash、标准化格式、补全元数据
注意:composer install 正常情况下绝不会修改 composer.lock;它只读取并按锁文件安装。只有两种例外会触发重写:composer.lock 缺失,或其 content-hash 与当前 composer.json 不匹配(比如你改了 description 却没同步锁)。
为什么改了 composer.json 却没更新 lock?
常见于以下情况:
- 只改了非依赖字段(如
name、description、scripts、空格缩进),而没碰require或require-dev—— 这时composer install会报错Your lock file is out of sync,但不会自动修复;必须用composer update --lock-only - 误加了
--dry-run参数,命令只是模拟,根本没写文件 -
composer.lock被.gitignore忽略,Git 不跟踪,导致你以为“没变”,其实是根本没提交过 - IDE(如 PHPStorm)后台静默执行了
composer install,干扰了你的手动判断
验证是否真被忽略:git ls-files | grep composer.lock;为空则需先 git add composer.lock。
CI/CD 和团队协作中 lock 文件怎么保鲜?
构建失败常源于 lock 格式非法、平台不匹配或哈希失效,而非依赖本身问题:
- CI 流水线里禁止出现
composer update;部署阶段只允许composer install --no-dev --no-interaction - 流水线开头可加预检:
composer update --lock-only --dry-run,若输出Would update lock file,就直接fail,强制开发者本地修复 - 多人合并导致
composer.lock冲突时,不要手动编辑;应git checkout --ours composer.lock+rm -rf vendor+composer install - 团队必须统一 Composer 大版本(推荐 2.x),否则老版本读不到新 lock 中的
content-hash或platform字段,直接报错
最容易被忽略的一点:Composer 版本差异不是“小问题”,而是会导致 lock 文件完全不可加载——它不是格式错误,是语义不兼容。CI 脚本里别用 composer self-update,应锁定具体版本,例如 composer self-update 2.5.8。











