composer update --lock-only 是唯一安全的“只更新 lock”方式:它仅重算锁文件哈希与格式,不修改 vendor、不升级包、不触发网络请求,且要求 composer 2.2+。

composer update --lock-only 是唯一安全的“只更新 lock”方式
当你改了 composer.json 里的非依赖字段(比如 "description"、"license"、空格或换行),但没动任何 require 或 require-dev,Composer 就会报错:Your lock file is out of sync with your composer.json。这时你根本不想升级任何包——只是要让 composer.lock 的哈希值和新 JSON 匹配。
✅ 正确做法:composer update --lock-only
❌ 错误做法:composer update(全量升级)、composer install(直接报错退出)、手动改 composer.lock(破坏一致性)
- 该参数仅在 Composer 2.2+ 可用;旧版本必须升级 Composer,不能靠“删 lock + install”来凑合
- 它会重新解析当前
composer.json的全部约束(包括新增/修改的包声明),并按已安装的版本重算锁文件,不下载、不替换 vendor 中任何文件 - 若你只想刷新格式或校验和(比如 Git 合并后 lock 文件损坏),该命令不适用——应改用
composer update --lock
想预览改动?先跑 --dry-run --lock-only
直接执行 composer update --lock-only 前,建议加 --dry-run 看一眼它到底打算改什么。尤其在团队协作或上线前,这步能避免意外带入子依赖变更。
运行:composer update --dry-run --lock-only
- 输出中会出现类似:
Would update lock file to reflect changes in composer.json,并列出 version、dist.shasum、require 字段将被刷新的具体包 - 如果看到本不该变的包出现在列表里,说明
composer.json中存在隐式影响(例如"^2.0"碰巧匹配了新 patch 版本),需回头检查约束是否过于宽松 -
--dry-run不写磁盘,也不触发网络请求,纯本地计算,非常快
别混淆 --lock-only 和 --lock
这两个参数名字像,作用却完全不同:--lock-only 是“重算锁”,--lock 是“重写锁”。前者响应 composer.json 变更,后者完全无视它。
-
composer update --lock-only:读取新composer.json,验证已安装包是否仍满足所有约束,然后生成新 lock —— 它可能发现某个包已不兼容,从而报错 -
composer update --lock:不查composer.json新内容,也不联网拉元数据,只对当前 vendor 目录做快照、校验、标准化格式后写回 lock —— 即使你在 json 里新加了一个包,它也视而不见 - 典型使用场景:
--lock适合修复 lock 文件损坏、统一 CI 中的 lock 格式;--lock-only才是解决 “JSON 改了但 lock 没同步” 的正解
为什么不能手动编辑 composer.lock?
有人为绕过约束,直接改 composer.lock 里的 "version": "3.5.0" 和 "shasum",以为这样就能“强制更新”。这是危险且无效的操作。
- Composer 在 install/update 时不仅比对 version,还会校验 dist 归档的完整哈希、依赖树结构、autoload 映射等;手动改 version 不等于改通整条链路
- 一旦哈希不一致,后续
composer install可能失败,或导致 autoloader 加载错误、类找不到 - 更严重的是:它破坏了 lock 文件作为“可重现构建契约”的本质——别人 checkout 你的代码后,
composer install还原出的环境将与你本地不一致
真正需要更新某个包,就用 composer update vendor/package;只需要同步 lock,就用 --lock-only。没有捷径,也没有“强制覆盖 lock”的合法路径。










