composer.lock 被修改是危险信号,因它本不该被 install 改动,意外提交会导致依赖树不一致;主因是误用 update 或环境差异(PHP 版本、扩展、Composer 版本)触发自动重生成。

为什么 composer.lock 被修改是危险信号
团队中任意成员执行 composer install 本不该改动 composer.lock;一旦它被意外提交,就会导致其他人拉取到不一致的依赖树。根本原因常是有人误用了 composer update,或本地 PHP 版本、平台配置(如 ext-mbstring 是否启用)与 CI/生产环境不一致,触发 Composer 自动重生成 lock 文件。
禁止修改 composer.lock 的实操手段
靠人盯不如靠机制。以下措施需在项目初始化阶段就落地:
- 在
.gitattributes中添加composer.lock -diff -merge,禁用 Git 合并冲突提示,同时让 diff 工具跳过该文件(避免误读变更) - CI 流水线第一步执行
composer install --no-interaction --prefer-dist后,立即校验git status --porcelain composer.lock,非空则直接失败 - 开发机预置 Git hook(如
.git/hooks/pre-commit),检查git diff --cached --quiet composer.lock,若返回非零值则拒绝提交 - 团队统一使用
composer install(不是update)来安装依赖;CI 和部署脚本也必须显式声明--no-scripts或--no-plugins,防止钩子意外触发更新逻辑
composer.json 中的关键约束配置
仅靠流程控制不够,还需在配置层收口:
- 设置
"platform": {"php": "8.1.10"},锁定 PHP 小版本,避免因本地 PHP 升级导致扩展可用性判断变化,进而影响composer.lock内容 - 禁用自动平台检测:在
config下加"platform-check": false,否则 Composer 会根据运行时环境动态调整平台包版本,造成 lock 文件漂移 - 所有 require 的包都应带精确版本号(如
"monolog/monolog": "3.5.0"),而非^3.5或*;否则install可能因仓库元数据刷新而解析出不同版本
CI 和本地环境必须保持一致的三个点
即使 lock 文件没变,依赖行为也可能不一致——这比 lock 被改更隐蔽:
- PHP 版本:Dockerfile / GitHub Actions 中用
php:8.1.10-cli这类带小版本的镜像,而不是php:8.1 - 扩展启用状态:通过
docker-php-ext-install显式开启mbstring、gd等,不要依赖基础镜像默认配置 - Composer 版本:CI 中固定用
composer:v2.5.8(查 官方发布页 确认),避免因 Composer 自身解析逻辑升级导致 lock 文件重写
update,而是不同环境对同一 composer.lock 的“解释结果”不一致——平台配置、PHP 补丁版本、Composer 解析器行为,三者缺一都会让 lock 文件失去意义。










