composer install 才是让本地 vendor 与 composer.lock 对齐的正确命令;update 必改 lock 并重算依赖,install 则严格按 lock 安装且通常不修改 lock,仅在 content-hash 不匹配等特殊情况下重写。

composer update 会改代码,composer install 才只同步 composer.lock
很多人想“只更新 lock 文件内容”,其实是误解了目标:你不是要“更新 lock”,而是要“让本地 vendor 和 lock 文件对齐”——这恰恰是 composer install 的本职工作。composer update 的作用是根据 composer.json 重新计算依赖、写入新版本到 composer.lock,并安装,它一定会改 lock,也一定会动 vendor。
常见错误现象:git status 显示 composer.lock 被修改,但你没运行 composer update —— 很可能是别人提交了 lock 文件,而你本地 vendor 缺失或不一致,却误用了 composer update 去“修复”,结果生成了带时间戳、哈希值差异的新 lock,引发合并不必要的冲突。
- 正确做法:只要 lock 文件已存在且你不想升级任何包,就只运行
composer install - 它会严格按 lock 中记录的版本、哈希、源地址安装,不查 packagist,不重算依赖树
- 如果 lock 文件里有平台配置(如
platform)或插件配置(如plugin-api-version),composer install也会校验并报错,而不是静默跳过
为什么 composer install 有时还是改了 composer.lock?
正常情况下它不该动 lock,但以下几种情况会导致意外重写:
-
composer.json和composer.lock的content-hash不匹配(比如手动编辑过 json 但没更新 lock)——install 会自动重写 lock 来同步 hash - lock 文件里记录的 PHP 版本(
platform)和当前运行环境不一致,且启用了config.platform.php覆盖,Composer 会重写 lock 中的 platform 段以反映实际环境 - 使用了
--no-scripts或--no-plugins等标志,导致某些插件无法执行初始化逻辑,部分插件(如hirak/prestissimo旧版)可能触发 lock 重生成
验证方式:运行 composer install --dry-run,它会模拟执行并告诉你是否需要重写 lock —— 如果输出里有 “would update lock file”,说明上面某条条件被触发了。
composer update --lock 是个假动作
这个命令在 Composer 2.2+ 才加入,但它**不做任何事**:它只是检查 composer.lock 是否能被解析、是否与 composer.json 基本兼容,然后退出。不会重写 lock,也不会安装包,连网络请求都不发。
- 它存在的唯一用途是 CI 流水线里的轻量校验:确保 lock 文件格式合法、没被破坏
- 如果你希望 lock 内容“更新”(比如合并分支后 lock 有冲突,你想用某一方的版本),必须先人工解决冲突,再运行
composer install验证是否可执行 - 别把它当成
npm install --package-lock-only的等价物——Composer 没有纯 lock 同步模式
多人协作时 lock 文件频繁冲突怎么办?
根本原因不是工具问题,而是团队没对齐依赖管理节奏。最常被忽略的一点是:composer.lock 不仅记录包版本,还记录完整哈希、下载源、PHP 平台约束——这些字段对换行符、JSON 格式、空格都敏感。
- 强制统一 Git 的换行符设置:在项目根目录加
.gitattributes,写入composer.lock text eol=lf - 所有成员禁用 IDE 自动格式化 lock 文件(PhpStorm/VS Code 默认会 prettify JSON,破坏原始缩进和键序)
- 避免混合使用 Composer 版本:1.x 和 2.x 生成的 lock 结构不同(如
packages-dev拆分),混用必然冲突 - 小范围更新依赖时,用
composer update vendor/package-name明确指定包,比全量update更可控
真正麻烦的从来不是怎么更新 lock,而是 lock 里藏着太多隐式上下文:PHP 小版本、扩展启用状态、甚至 CI 环境里的代理配置。这些细节一旦漏掉,composer install 就会静默降级或跳过某些包,而你只在部署时报错。










