composer install必须读composer.lock,因其设计目标是“原样还原”:严格按锁文件中的精确版本号、dist URL、sha256校验值和完整依赖树安装,完全忽略composer.json中的^或~版本约束。

因为没有 composer.lock,composer install 就不是安装,而是隐式执行一次不可控的 composer update。
为什么 composer install 必须读 composer.lock
composer install 的设计目标从来不是“满足版本约束”,而是“原样还原”——它只认 composer.lock 里写的精确版本号、dist URL、sha256 校验值和完整依赖树,完全忽略 composer.json 中的 ^7.0 或 ~2.5。
- 常见错误现象:
Class 'Symfony\Component\HttpClient\HttpClient' not found—— 本地能跑、CI 报错,大概率是composer.lock没提交或被.gitignore误删 - 同事装出
guzzlehttp/guzzle7.8.1,你装出7.9.0,但两人都没动composer.json?说明lock缺失,install实际执行了隐式update - 性能影响:跳过整套依赖解析过程,安装速度显著快于
update;无lock时首次install不仅慢,结果还不可复现
删掉 composer.lock 会发生什么
等价于主动放弃环境一致性契约,不是“重新生成”,而是“重抽一次签”:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 子依赖可能悄悄降级(比如
monolog/monolog从2.9.1退到2.8.0,触发已知日志丢失 bug) - 也可能升级到带 BC break 的小版本(如
phpunit/phpunit从9.6.15升到9.6.16,assertStringContainsString()行为变更) -
composer install不会报错,但会静默生成新lock,且content-hash字段已变,后续composer validate会警告The lock file is not up to date
Git 冲突时为什么不能手动编辑 composer.lock
它不是普通 JSON 配置文件,而是整个依赖图的完整序列化快照,字段顺序、空格、哈希值都参与校验:
- 手动删冲突标记、保留“这边的包 + 那边的哈希”、用格式化工具“美化”——99% 导致后续
composer install失败或运行时Class not found - 正确做法是先确保
composer.json已合并完成(可用git checkout --theirs composer.json快速采纳远端),再执行:-
git checkout --ours composer.lock或git checkout --theirs composer.lock(任选其一恢复) rm -rf vendor/-
composer install—— 它会基于当前composer.json和刚恢复的lock校验并生成新lock
-
- 如果提示
Your lock file does not contain a compatible set of packages,说明composer.json已被他人修改,先git pull,再composer install
真正容易被忽略的点在于:composer.lock 的效力依赖于基础环境的一致性——比如 platform 配置不匹配、PHP 版本差异、甚至不同 Composer 主版本生成的 lock 结构顺序不同,都可能导致看似相同的文件内容,在不同机器上触发校验失败或依赖漂移。

















