composer.lock 是项目依赖的精确版本快照,记录所有包的完整版本、下载地址、校验和及依赖树结构,必须提交至 Git 以保障构建可重现;应用项目须提交,库项目则不应提交。

composer.lock 是依赖的“快照”,不是缓存文件
它不是临时生成、可随意删掉的中间产物,而是项目当前所有依赖(包括子依赖)的精确版本快照。只要存在 composer.lock,composer install 就会严格按它安装——不联网解析、不重新选版本、不考虑 composer.json 里的 ^2.0 或 ~1.5 这类范围约束。
- 记录每个包的 exact version:比如
"monolog/monolog": "2.9.1",不是"^2.0" - 保存每个包的
dist下载地址和 SHA-256 校验和,确保下载内容未被篡改 - 完整记录依赖树结构,连
psr/log被哪个包间接引入、用了哪个版本,都写得清清楚楚
为什么必须提交到 Git?团队协作中不提交等于埋雷
不提交 composer.lock,就等于把“线上跑的代码到底依赖什么版本”这个问题交给运气。本地能跑,CI 报错,生产崩了查不出原因——90% 都是这个文件没进仓库导致的。
- CI/CD 流水线执行
composer install时,靠的就是 lock 文件跳过解析;没它,每次构建都可能拉到不同小版本 - Git 切到旧 commit 后,
composer install能立刻还原当时那套依赖;没 lock 文件,你根本不知道那个 commit 对应哪套依赖 - 安全扫描工具(如
composer audit)依赖 lock 文件里的完整依赖图谱,没它就扫不出深层漏洞
注意:只有应用项目(application)才必须提交;如果你在写一个会被别人 require 的开源库(library),则不应提交自己的 composer.lock。
发生 Git 冲突时,千万别手动合并 lock 文件
composer.lock 是自动生成的 JSON,结构复杂、字段多、嵌套深,手动改极易出错。一旦冲突,标准解法只有一个:
- 先解决
composer.json的冲突(比如两人同时加了新包,或改了同一包的版本) - 保存合并后的
composer.json - 运行
composer update(或更精准地用composer update vendor/package) - 提交新生成的
composer.lock
这样生成的 lock 文件才是逻辑一致、可验证的。强行保留某一方的 lock + 手动 patch,轻则 autoload 失败,重则运行时抛出 Class not found 或方法签名不匹配。
日常开发中,什么时候该用 install,什么时候该用 update?
一句话区分:install 是还原,update 是变更。绝大多数时候,你只需要 composer install。
- 刚克隆项目、CI 构建、上线部署 → 用
composer install(含--no-dev) - 新增依赖:
composer require monolog/monolog后自动更新 lock,再提交 - 升级已有依赖:
composer update monolog/monolog,验证通过后再提交 lock - 修复安全漏洞:
composer update --with-dependencies或composer audit --fix
最常踩的坑是:以为 composer install 会“自动更新”——它不会。它只认 lock 文件;没有 lock,才退化成解析行为,而这恰恰是你要避免的不可控状态。
真正关键的不是记住命令,而是理解「lock 文件 = 可重现性的唯一事实来源」。哪怕你用 Docker、用 Nix、用全栈隔离环境,只要构建阶段调了 composer install,它就绕不开这个文件。忽略它,就等于放弃对依赖的控制权。










