必须提交 composer.lock 文件,它是确保所有环境依赖版本完全一致的唯一依据;不提交会导致依赖漂移、CI失败、上线报错及团队环境不一致等问题。

因为 composer.lock 是唯一能确保所有开发者和生产环境安装完全相同依赖版本的文件。
不提交 composer.lock 会导致依赖漂移
当你只提交 composer.json,不同人执行 composer install 或 composer update 时,Composer 会根据当前仓库状态、网络缓存、PHP 版本、甚至时间戳,解析出不同的依赖树。哪怕只是小版本号(如 monolog/monolog v2.10.0 → v2.10.2),也可能引入不兼容的变更或未预期的行为。
常见错误现象:
- 本地运行正常,CI 构建失败(
Class not found或Method does not exist) - 测试通过,上线后报错(某依赖在新小版本中移除了一个被你直接调用的私有方法)
- 同事 A 和 B 的
vendor/目录结构不一致,导致 IDE 提示异常或自动补全失效
composer install 与 composer update 行为差异
团队协作中必须明确区分这两个命令的用途:
-
composer install:读取已存在的composer.lock,精确还原依赖版本 —— 这是日常开发、CI、部署时应使用的命令 -
composer update:忽略composer.lock,重新解析composer.json并生成新锁文件 —— 仅在主动升级依赖时使用,且必须提交更新后的composer.lock
如果没提交 composer.lock,composer install 实际退化为 composer update,失去“锁定”意义。
CI/CD 和生产环境依赖一致性依赖它
现代部署流程通常包含:
- CI 节点执行
composer install --no-dev(需存在composer.lock) - Docker 构建中
COPY composer.lock .后再composer install - 线上服务器从 Git 拉取代码后,靠
composer.lock确保和测试环境一致
没有 composer.lock,你就无法回答:“这个发布包到底用了 symfony/http-kernel 的哪个 commit?”
# 正确的 Git 提交流程示例 git add composer.json composer.lock git commit -m "feat: add guzzlehttp/guzzle ^7.8"
最容易被忽略的一点:很多人以为“只改 composer.json 就够了”,结果在 CI 中发现 composer install 报错说找不到某个包的特定版本 —— 那是因为那个版本根本没写进 composer.lock,而本地又恰好缓存过。提交 composer.lock 不是“多此一举”,是把“当时确认可行的完整依赖快照”显式固化下来。










