必须先协调 composer.json 再执行 composer update --lock 重生成 lock 文件,因冲突源于语义化版本约束不可共存;直接 install 会因 json 与 lock 不匹配而报错。

分支合并时出现 Composer 依赖冲突,不是“版本没对上”,而是两个分支的 composer.json 对同一包提出了无法共存的语义化约束——必须先协调 composer.json,再用 composer update --lock 重生成 composer.lock,不能跳过这一步直接 composer install。
为什么 composer install 会直接报错 “Your lock file does not contain a compatible set of packages”
这个错误不是说 composer.lock 文件坏了,而是当前 composer.json 和 composer.lock 记录的依赖图不匹配。常见于:一个分支升级了 laravel/framework 到 ^11.0,另一个还卡在 ^10.40,而它们各自 composer.lock 都只记录了自己能跑通的子依赖树。Git 合并后,composer.lock 被手动“拼凑”或选了一边,但 composer.json 里可能已混入两套约束,composer install 校验时发现根本没法还原出一致的 vendor 状态。
- 先运行
git status,确认composer.json是否也存在冲突 —— 如果有,必须优先解决它,这是唯一需要人工比对的文件 - 如果
composer.json已 clean,但composer install报错,大概率是composer.lock里残留了 Git 冲突标记(如),PHP JSON 解析器直接拒读 - 别信 CI 日志里 “Lock file is outdated” 的提示 —— 它只是表象,根因永远在
composer.json的约束交集是否为空
composer why-not 是定位阻塞链的第一步,不是 composer depends
看到报错里写着 “Conclusion: don’t install guzzlehttp/guzzle:^7.5”,别急着改 composer.json。先敲:composer why-not guzzlehttp/guzzle:^7.5。它会输出真实拦路的依赖路径,比如:
myapp/core dev-main requires monolog/monolog (^2.9) monolog/monolog ^2.9 requires guzzlehttp/guzzle (^6.5)
这说明问题不在你当前想装的包,而在 monolog/monolog 的约束太窄。接着顺藤摸瓜:composer why monolog/monolog,看是谁把它拉进来的 —— 往往是某个私有 SDK 或 require-dev 里的测试工具锁死了旧版。
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
-
composer depends查的是“谁依赖它”,composer why才查“为什么它被装进来”,后者才能暴露真实依赖路径 - 注意
require-dev里的包:比如orchestra/testbench可能硬绑 Laravel 9,而主项目已升到 10,这种隐式冲突最常被忽略 - 如果
why-not输出里出现dev-main或私有包名,优先去那个包的composer.json改约束,而不是动主项目
合并前用 composer update --lock 统一快照,不是可选项
功能分支开发完,合入 main 前,不要直接 push。先切回 main 拉最新:git checkout main && git pull,再切回来:git checkout my-feature,然后执行:composer update --lock。
- 这个命令只重写
composer.lock文件结构(哈希、顺序、platform-check),不改变任何包版本,也不碰vendor - 它会让当前分支的
composer.lock和main的composer.json对齐,大幅降低后续 merge 时的冲突范围 - 如果执行时报 “Your requirements could not be resolved”,说明
my-feature的composer.json和main存在真实不兼容(比如 PHP 版本要求冲突),这时必须人工协调composer.json,不能硬上
CI 流水线里禁用 --no-lock,加 composer validate --strict
很多团队为“绕过 lock 冲突”在 CI 脚本里加 composer install --no-lock,结果上线环境装的包和本地完全不一样。这不是解法,是埋雷。
- CI 第一步必须加
composer validate --strict:它会校验composer.json语法、字段合法性,以及composer.lock是否与当前composer.json匹配 - 如果校验失败,CI 应直接挂掉,并提示 “Please run
composer update --lockand commit the new lock file” - 修复脚本可以这么写:
rm composer.lock && composer install && git add composer.lock,但仅限于 PR 自动修复场景,不能替代人工 review
真正难处理的从来不是冲突本身,而是两个分支各自升级了同一个包(比如都动了 guzzlehttp/guzzle),但没人同步沟通升级意图。锁文件冲突只是表象,背后是依赖变更流程失控。把 composer.json 变更纳入 PR checklist,比任何工具都管用。










