composer.json的require冲突必须手动合并,需逐行比对两边包名与版本,统一为语义兼容写法(如“^1.25”),通过json_decode校验语法,再删vendor和composer.lock,执行composer update --lock重建依赖树。

composer.json 的 require 冲突必须手动合并,不能跳过
Git 合并时两个分支各自新增了不同包,composer.json 的 require 段出现冲突,这是真正需要人工介入的地方。Composer 不会帮你“猜”该保留哪个包,它只认最终 JSON 结构是否合法、是否能推导出一致依赖树。
常见错误是直接删掉冲突标记、留一边、或用 IDE 自动合并——结果往往是漏掉某个 vendor/package,或者版本号写成 "^1.0.0" 和 "1.0" 混用,导致后续 composer update --lock 失败。
- 逐行比对两边的
require列表,确认哪些包是 A 分支独有、哪些是 B 分支独有、哪些是共有的但版本不同 - 对共有包,优先采用语义化兼容写法,比如把
"monolog/monolog": "1.25.0"和"monolog/monolog": "^1.26"统一为"^1.25" - 运行
php -r "json_decode(file_get_contents('composer.json'), null, 512, JSON_THROW_ON_ERROR);"验证语法正确性,避免因逗号缺失或引号不闭合导致静默失败 - 不要在
require里混用dev-main和^3.0—— 稳定性不一致会放大后续解析难度
composer.lock 冲突一律删除重生成,别缝合
composer.lock 是快照,不是配置文件。Git 合并时出现 <<<<<< HEAD 标记,说明两个分支的依赖树已经分叉,手动拼接只会制造 content-hash 不匹配、dist.url 残留、packages-dev 和 packages 版本错位等隐性问题。
典型症状包括:Package xxx not found、Invalid argument、甚至 composer install 成功但运行时报类找不到——因为部分包被跳过安装。
- 确认
composer.json已无冲突且通过 JSON 校验后,彻底删除本地vendor/目录和composer.lock - 执行
composer update --lock(不是install),让 Composer 从当前composer.json重算整棵树 - 如果报错如
requires php ^8.1 but your PHP version (7.4.33),说明你终端调用的 PHP 版本不匹配,先运行php -v和which php定位二进制路径 - CI 环境若需固定 PHP 版本,请用
config.platform.php,但本地开发请禁用它——它会掩盖真实环境不一致问题
feature 分支里怎么避免 lock 文件污染
多人协作中,90% 的 composer.lock 冲突源于 feature 分支频繁执行 composer update,导致每个分支都生成了不可比对的快照。这不是 Git 的问题,而是开发习惯问题。
理想流程是:增删包用 composer require 或 composer remove,它们会自动更新 composer.lock;升级关键依赖前,先跑 composer why-not vendor/package:target-version 确认影响面。
- 开发中只允许执行
composer require xxx、composer remove xxx、composer update vendor/package --no-install(仅改 JSON) - 合入主干前,在 feature 分支上执行一次
composer update --lock,确保 lock 哈希与当前 composer.json 严格对应 - 禁用 Git 的 auto-merge 配置对
composer.lock生效:在项目根目录加.gitattributes,写入composer.lock merge=ours,防止意外触发合并 - 不要装
composer-merge-plugin—— 它已停止维护,且官方明确反对多源 lock 合并逻辑
冲突解决后为什么 dump-autoload 还要再跑一遍
composer update --lock 只保证包下载和 vendor/autoload.php 入口存在,但不会刷新 PSR-4 映射或 classmap 缓存。尤其当分支间涉及框架升级(如 ThinkPHP 6.0 → 6.1)、或更换了 facade 加载方式时,旧的 autoload 配置可能残留。
典型表现是:类文件明明在 vendor/ 里,却报 Class not found;或者 IDE 提示正常,运行时报错。
- 执行
composer dump-autoload -o强制重建优化后的自动加载映射 - 如果用了自定义
autoload.files或autoload.psr-4,检查路径是否仍指向已删除的旧包目录 - ThinkPHP 6.1+ 默认关闭 alias 映射,旧代码若依赖
config/app.php中的'alias' => [],需改用容器绑定或 PSR-4 命名空间引用 - 某些扩展包(如
topthink/think-swoole)会覆盖默认 autoload 行为,冲突解决后建议验证其服务是否正常注册
composer.json 合并后没校验 JSON 有效性,就急着重生成 lock;或者重生成 lock 后没跑 dump-autoload,导致类加载链断裂。这两步看似简单,却是多数“明明解决了冲突却还是跑不起来”的根源。


















