composer.lock 是依赖的精确快照,必须提交至 Git;它记录每个包的确切版本、哈希值与完整依赖树,确保 composer install 在所有环境安装完全一致的依赖,避免因版本波动引发兼容性问题。

composer.lock 是依赖的“快照”,不是可选附件
它记录的是当前项目 vendor/ 目录里**每一个包的确切版本、源码哈希、dist 地址、完整依赖树**——不是你“想装什么”,而是你“实际装了什么”。没有它,composer install 就会退化成按 composer.json 重新解析版本,同一行 "monolog/monolog": "^2.5" 在 CI、测试机、生产服务器上可能分别装出 2.5.0、2.8.2、2.9.3,而其中某个 patch 版本可能悄悄改了返回类型或废弃了一个方法。
- 必须提交到 Git,和
index.php或.env.example一样关键 - CI/CD 部署时只允许用
composer install(读 lock),严禁用composer update - 本地开发时若删了它,
composer install会重建,但结果不可控——这不是“重装”,是“重算”
composer.json 和 composer.lock 的分工非常明确
composer.json 是人写的说明书:require 告诉 Composer “我需要 monolog,至少 2.0”,autoload 告诉它“我的类怎么加载”。它管意图,不保结果;composer.lock 是机器生成的收据:它写明“这次装的是 monolog v2.9.1,dist 包 SHA256 是 xxx,它的依赖 psr/log 是 v1.2.3,也一起锁死了”。只要 lock 文件存在,Composer 就完全忽略 json 里的 ^ 或 ~ 约束,只认 lock 里写的 exact version。
- 改需求?编辑
composer.json,然后运行composer update monolog/monolog - 同步环境?拉代码后直接
composer install,别手痒去update - 合并分支遇到 lock 冲突?优先保留对方的 lock,再跑一次
composer update --dry-run验证是否引入意外变更
常见错误:手动编辑 lock 文件 or 忽略它
有人看到某依赖版本太低,就直接打开 composer.lock 把 "version": "2.1.0" 改成 "2.9.1"——这会导致哈希校验失败,下次 composer install 会报错退出;还有人觉得“反正 json 里写了范围,lock 不重要”,于是 .gitignore 里加了 /composer.lock,结果上线后发现日志突然不写了,查半天才发现 monolog 被自动升到了 v3,而项目代码还调用着已被移除的 Logger::getLevel()。
- lock 文件结构复杂,含嵌套依赖、多层哈希、dist/source 切换逻辑,手工维护=自找麻烦
- 要升级?用
composer update vendor/package,它会自动更新 lock 并校验一致性 - 要回退?用
git checkout HEAD~1 -- composer.lock && composer install,而不是改 json 后硬装
vendor/composer/installed.json 是另一个容易被误解的文件
它不是 lock,也不是 json,而是 Composer 在每次安装成功后,对 vendor/ 目录做的“现场拍照”:记录每个已安装包的路径、autoload 配置、是否为 dev 依赖等。它不参与版本控制,也不决定安装行为,只是 vendor/autoload.php 生成时的数据源。你不需要管它,也不该提交它到 Git。
-
composer show --installed显示的内容,就来自这个文件,不是 lock - 部署工具(如 Capistrano 插件)有时靠它确认
vendor/是否完整,而非只看目录是否存在 - 删掉它?下次
composer install会自动重建;改它?没用,会被覆盖
真正难的不是理解 lock 文件的作用,而是团队里每个人都坚持「改 json 就 update,拉代码就 install,lock 必须进 Git」——一旦有一个人跳过流程,一致性就崩了。










