必须提交 composer.lock,它是精确锁定所有依赖版本、源类型和校验和的关键文件,忽略会导致环境间依赖不一致,引发运行时错误、类型不匹配或行为变更。

要提交,必须提交。忽略 composer.lock 会导致团队成员、CI/CD 环境和生产环境安装不一致的依赖版本,哪怕只差一个小版本,也可能引发运行时错误、类型不匹配或静默行为变更。
为什么 composer.lock 不是“临时文件”
它不是缓存,而是精确锁定:记录了每个包(包括所有嵌套依赖)的完整名称、确切版本号、源类型(dist/git)、commit hash(对 Git 包)、校验和(dist.shasum)。没有它,composer install 就退化为 composer update 的弱化版——每次都会按 composer.json 中的版本约束重新解析依赖图,结果不可控。
- PHP 8.2 下
monolog/monolog ^2.0可能装2.10.0,而 PHP 8.3 下装到2.11.0(后者已弃用某个方法) - CI 流水线通过,线上部署却因
guzzlehttp/guzzle补丁版本差异触发 DNS 解析超时 bug - 同事
composer install后vendor/autoload.php加载失败,因为psr/container被升级到了 v2,但你的代码仍用 v1 接口
哪些情况会意外绕过 composer.lock
常见于本地开发误操作或 CI 配置疏漏:
- 执行了
composer update但没提交新生成的composer.lock—— 这是最高频事故源 - CI 脚本写成
composer install --no-lock(仅应在调试依赖冲突时临时使用) -
.gitignore里错误地包含/composer.lock或composer.lock - 项目从 Packagist 切换到私有仓库后,未运行
composer update更新 lock 文件中的源信息
composer install 和 composer update 的分工必须明确
二者目的完全不同,混用是多数 lock 文件问题的根源:
-
composer install:仅读取现有composer.lock,严格复现已知可工作状态 —— 这是部署、CI、新同事拉代码后的唯一正确命令 -
composer update:忽略 lock,根据composer.json重新计算并写入新 lock —— 仅在主动升级依赖、修复安全漏洞或解决兼容性问题时手动触发 - CI 中若需更新依赖(如 nightly 安全扫描),应显式运行
composer update --dry-run并人工审核变更,而非无条件update
真正容易被忽略的是:lock 文件里的 content-hash 字段。它由 composer.json 内容生成,一旦你改了 json 却没运行 update 或 install,lock 文件就处于“逻辑不一致”状态 —— Git 提交时不会报错,但下次别人 install 会失败或降级。这个哈希值才是 Composer 判断是否需要警告的底层依据。










