必须用 composer update --lock 重建,不可手动修改;它是依赖树的精确快照,字段顺序、packages 排列、platform 和哈希值均有语义,Git 合并会破坏完整性导致 install 失败或静默错误。

Composer.lock 冲突难搞,根本不是 Git 合并逻辑的问题,而是你把它当普通 JSON 文件在处理——它其实是依赖图的加密快照,改错一行哈希或漏掉一个 ext-xyz 声明,composer install 就会静默装错、运行时报 Class not found 或 CI 直接失败。
为什么手动解决 composer.lock 冲突必踩坑
Git 标出的冲突块()一旦保留在文件里,<code>composer install 会直接报 JSON decode error;就算侥幸跳过解析,以下问题也逃不掉:
-
packages数组顺序错乱 → 自动加载器注册顺序异常,class_alias失效或 trait 加载失败 -
dist.sha256值被手工覆盖 → 下次install提示Invalid archive signature - 平台约束字段(如
platform-check或php版本)只留了一边 → CI 因ext-gd缺失而中断,但本地不报 - 用
git checkout --ours强行保留某方 lock → 实际依赖状态已偏离对方composer.json,install可能跳过新 require 的包
composer update --lock 是唯一安全重建方式
冲突发生后,别修 lock,先确保 composer.json 已合并完成(包括 require、require-dev、config 全部字段),再重建 lock:
- 删掉本地
vendor/和composer.lock(避免残留缓存干扰) - 运行
composer update --lock --no-install:只生成 lock,不重装 vendor,输出里检查是否出现非预期的降级或跳过 - 确认无误后
git add composer.lock,提交信息写清变更依据,例如lock: sync php 8.3 platform + monolog ^3.0 - CI 中加
composer install --dry-run校验,失败即阻断合并,不给“假装同步”留余地
怎么让 lock 冲突只在该出现的地方出现
高频冲突本质是多人无序修改依赖。真正要控的不是 Git,而是操作节奏和校验点:
- 全局启用
sort-packages:composer config -g sort-packages true,消除因包顺序不同导致的“假冲突” - 禁用全量
composer update,改用composer update vendor/package --with-dependencies精确控制影响范围 - 所有新成员加入前,必须确认本地已执行上述全局配置,否则第一次
composer require就会打乱 lock 顺序 - 在
composer.json顶层加{"config": {"lock": true}},让composer install在json改了但lock没更新时直接报错,不给你机会装错
CI 和部署脚本里最容易被忽略的陷阱
不是 lock 没提交,而是缓存机制让它“假装存在”:
- GitHub Actions / GitLab CI 默认可能复用旧的
composer.lock缓存 → 必须第一步加ls -la composer.lock,确认文件存在且时间戳与当前 commit 匹配 - 禁用 vendor 缓存,或显式声明
cache: false(某些平台需强制关闭) - 部署命令别只写
composer install --no-dev,必须加--(防止参数被误解析),且建议补上--no-interaction --optimize-autoloader - 如果用了私有仓库,CI 脚本开头要加
composer config --global github-oauth.github.com $GITHUB_TOKEN,否则元数据拉不到
最常被跳过的一步,是没把 composer.lock 当合同——它不是生成一次就扔的快照,而是每次 composer.json 变更后必须同步更新的契约。谁改了依赖,谁负责跑 update --lock 并提交,而不是等合并时靠运气挑哪边的 lock 更“新”。


















