composer.lock 锁定的是实际安装的每个包的精确版本号、源类型、哈希值及完整依赖树快照;提交它可确保各环境依赖一致,不提交会导致构建和运行结果不可预测。

composer.lock 文件到底锁定了什么?
它锁定的不是 composer.json 里写的模糊范围(比如 "^2.5"),而是实际安装的每一个包的**精确版本号、源类型(git commit / dist zip)、哈希值、以及整棵依赖树的完整快照**。比如 monolog/monolog 最终装的是 2.9.1,它的子依赖 psr/log 是 1.1.4,连 symfony/polyfill-mbstring 的具体 commit hash 都记下来了。
这意味着:composer install 不再需要“猜”该装哪个版本——它只读 composer.lock,然后原样下载安装。没有这个文件,同一行 "monolog/monolog": "^2.5" 在不同时间、不同机器上可能装出 2.5.0、2.8.2 甚至 2.9.3,只要它们满足 ^2.5。
为什么必须提交到 Git?不提交会怎样?
不提交 composer.lock,等于把“依赖一致性”交给运气。常见后果包括:
- 本地能跑,CI 构建失败(因为 CI 拉的是最新兼容版,可能含 BC break)
- 测试环境通过,生产部署后报错(比如某 patch 版本悄悄改了返回类型)
- 同事拉代码后
composer install装出不同版本,两人调试同一段逻辑却行为不一致 - 某天上游包被删或重命名,没 lock 文件就无法复现历史构建
提交它,就是把“当前可工作的依赖状态”固化为项目不可分割的一部分——就像你不会只提交 package.json 却不提交 package-lock.json 一样。
遇到 composer.lock 冲突怎么办?
冲突不是 bug,是多人同时修改依赖的自然信号。处理原则是:**不要手动编辑 composer.lock,而要靠 Composer 重建**。
典型流程:
- 先
git stash或解决其他代码冲突 - 运行
composer install(确保本地composer.json已合并正确) - Composer 会自动根据合并后的
composer.json重新计算并生成新的composer.lock - 检查新生成的 lock 文件是否合理(比如没意外升级大版本),然后
git add composer.lock提交
切忌用文本编辑器手动改 lock 文件里的版本号——结构复杂、易出错,且哈希校验会失败。
哪些项目可以不提交 composer.lock?
极少数情况:你正在开发一个**纯库(library)**,即别人通过 "your/package": "^1.0" 引入你的项目,而不是直接部署运行它。这时你只提供 composer.json,由使用者自己生成 lock 文件。
但只要你项目是**可部署的应用(app)**——网站、API、CLI 工具、Laravel/Symfony 项目——composer.lock 就是必需品,和 index.php 一样重要。漏掉它,等于发布软件时不打包依赖。
最容易被忽略的一点:lock 文件的哈希值校验机制是静默生效的。它不报错,但一旦内容被篡改或损坏,composer install 可能跳过验证直接装错包——所以务必确保它始终在 Git 中受控、可追溯。










