手动合并 composer.lock 一定出问题,因为其字段顺序、content-hash、platform 和 dist.sha256 均具语义,git 冲突标记(如

不是 Git 冲突没解决干净,而是你直接保留了某一方的 composer.lock —— 这会导致 content-hash 与当前 composer.json 不匹配,后续 composer install 必然失败。
为什么手动合并 composer.lock 一定出问题
Git 合并时出现的 composer.lock 就是非法 JSON;即使你手动删掉了标记,只要没重建锁文件,content-hash 字段仍绑定着旧的依赖快照(含 PHP 版本、config.platform.php、字段顺序等),而你的 composer.json 已被修改过。结果就是:composer install 读到哈希不匹配,直接拒绝执行。
- 错误典型提示:
Content hash mismatch, lock file is not up to date或Root composer.json requires ..., but that version is not present in the lock file - CI 构建失败最常见原因:本地用 PHP 8.2 执行了
composer update,同事在 PHP 8.1 下生成了另一份composer.lock,两者content-hash天然不同 - 不要用
git checkout --ours或--theirs直接覆盖composer.lock—— 它们只解决文本冲突,不解决语义一致性
必须执行的三步重建操作
任何“选一个保留”的做法都跳过了依赖快照重算这一步,等于把炸弹留给了下一个人。真正有效的流程只有这一条路径:
- 先确保
composer.json已 clean merge:手动检查require、require-dev、config.platform.php等关键字段是否整合完整;若不确定,用git checkout --theirs composer.json拿主干版本再补上自己的新增项 - 删除当前
composer.lock和整个vendor/目录(避免旧缓存干扰解析) - 运行
composer update --lock:它不读旧 lock,只基于当前composer.json重算全部依赖树和哈希值;预期输出是Lock file operations: 0 installs, 0 updates, 0 removals,否则说明composer.json还没对齐
flock 报 “Cannot open lock file” 怎么办
这个错误和 Git 冲突无关,是 flock 机制本身的前提没满足:目标文件必须存在且可写。CI 首次构建、新分支 checkout 后常遇到。
- 先确认
composer.lock是否真实存在:ls -l composer.lock;若为空或被.gitignore排除,需从main分支复制一份干净副本 - 权限问题:Docker 中注意挂载卷是否为
ro,或容器内 UID/GID 与宿主机不一致导致无写权限 - NFS / WSL2 / Git for Windows 环境下
flock ./composer.lock本质失效(底层不支持 POSIX 锁),应改用flock .git -c 'composer install'或直接依赖 CI 平台级锁(如 GitHub Actions 的concurrency)
为什么 --no-interaction 不能防并发冲突
这个参数只关掉提示,完全不影响文件读写顺序。多个 composer install 进程仍会同时读同一份 composer.lock、各自解析、并行写 vendor/,最后可能都尝试覆盖 composer.lock —— 谁后完成谁赢,但没人校验哈希是否被篡改。
- 真正串行化必须发生在 shell 层,靠 OS 级锁阻塞对
composer.lock的写入路径 -
--prefer-dist、--no-plugins等也都是下载/加载策略,不改变并发模型 - 部署阶段最稳方案:禁用插件 + 预生成 lock,即只跑
composer install --no-interaction --no-plugins --optimize-autoloader,彻底避开写 lock 动作
复杂点在于:content-hash 绑定的是整个环境上下文,不是单纯文件内容。哪怕两个 composer.lock diff 看起来只差一行,只要生成时 PHP 版本或 Composer 版本不同,它们就无法互换。别试图“修”冲突,要“重算”。











