直接删 composer.lock 再 run composer install 是错的,会跳过 dev 依赖、忽略平台配置,导致本地与 CI 环境不一致;正确做法是删 lock 和 vendor 后运行 composer install --no-scripts 重建锁文件。

直接删掉 composer.lock,再跑一次 composer install 就能同步——但这是错的,会跳过 dev 依赖、忽略平台配置,导致本地和 CI 环境不一致。
为什么 composer install 报 “Your requirements could not be resolved”
这不是网络或缓存问题,而是 composer.lock 记录的依赖快照与当前 composer.json 的约束已不匹配。常见于:
- 手动改过
composer.json但没运行composer update或composer require - 从别人分支拉了新
composer.json,却保留了旧composer.lock - CI 构建时用了缓存的 lock 文件,但
composer.json已更新
此时 composer install 仍会尝试按 lock 文件装包,但发现某包在 lock 里声明的版本根本无法满足 composer.json 新增的 PHP 版本要求或新依赖约束,于是报错。
正确重建 lock 文件的三步操作
目标是让 composer.lock 完全反映 composer.json 当前状态,同时保留所有平台配置(如 config.platform.php)和 dev 依赖:
- 确认
composer.json已是最终期望状态(无 Git 冲突、字段完整) - 删除
composer.lock和vendor/目录(rm -f composer.lock vendor/) - 运行
composer install --no-scripts—— 这会基于composer.json重新生成composer.lock,且不执行 post-install-cmd 等脚本(避免因 autoload 未生成而中断)
完成后检查:composer show --tree | head -10 应与 composer.json 中的 require 列表基本对应;cat composer.lock | jq '.packages | length' 应明显多于仅运行 composer install 后的数量(说明 dev 包也进去了)。
Git 合并后出现 lock/json 不一致的典型场景
多人协作中,最常踩的坑不是锁文件冲突本身,而是合并后没验证一致性:
- 用
git merge --no-ff合并分支后,只解决了composer.json的文本冲突,却保留了自己旧的composer.lock - CI 流水线里没加
composer validate步骤,导致非法 JSON 的 lock 文件被提交(比如 Git 自动合并出) - .gitattributes 缺失,Git 对
composer.lock使用默认文本合并策略,产出语法错误的 JSON
补救方式不是重跑 composer update,而是先 git checkout --theirs composer.lock 拿回对方生成的合法 lock,再 composer install 验证能否装通。若失败,说明对方的 lock 本身就不兼容你的 composer.json,必须退回上一步人工核对变更点。
权限问题导致同步失败的隐蔽原因
尤其在 Docker 或 GitHub Actions 中,composer install 看似成功,但生成的 composer.lock 实际没写入,或写入的是空文件:
- 检查
ls -l composer.lock:若显示-r--r--r--,说明只读,Composer 会静默跳过写入 - Docker 构建阶段需加
RUN chmod u+w composer.json composer.lock - GitHub Actions 中
actions/checkout@v4默认read-only: true,必须显式设为false
这类问题不会报错,但后续 composer show 查不到刚 require 的包,composer.lock 时间戳也不变——本质是“假装同步了”,实际什么都没发生。


















