discard-changes 仅控制 vendor 目录下手动修改文件被覆盖时是否交互确认,不参与依赖解析;防版本冲突应使用 conflict 字段在 composer.json 中声明。

discard-changes 不是用来防版本冲突的,它解决的是「本地修改被覆盖时是否交互确认」的问题。如果你在 vendor/ 里手动改过某个包的代码(比如临时 patch),执行 composer update 就会卡在 Discard changes [y,n,v,d,s,?] 提示上——它和 conflict 完全无关,别混用。
为什么 discard-changes 常被误认为能防冲突
因为两者都出现在 composer.json 的 config 块里,且都跟“阻止某些行为”有关,但作用域完全不同:
-
discard-changes只影响vendor/目录下已安装包的文件是否被强制覆盖,不参与依赖解析 -
conflict在依赖解析阶段起效,由 SAT 求解器判断是否允许某版本进入依赖树 - 即使你设了
"discard-changes": true,Composer 依然可能装上一个你用conflict明确禁止的版本——只要它没被解析出来,这个配置就根本不会触发
discard-changes 的真实使用场景
它只在以下情况生效:
- 你手动编辑过
vendor/some/package/src/File.php - 执行
composer update some/package或composer install时,该包有新版本要下载 - Composer 发现本地文件有改动,且新版本内容不同,于是准备覆盖——这时才弹出交互提示
所以它本质是「覆盖策略开关」,不是「安全防护栏」。自动化部署中加 -n 或配 discard-changes: true,只是为了跳过人工确认,避免卡住。
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
真正防冲突该用 conflict 字段
想阻止某个有 bug 的版本被装上,必须写进 composer.json 的 conflict 区块:
{
"conflict": {
"monolog/monolog": "2.10.0",
"guzzlehttp/guzzle": ">=7.5.0 <7.5.2"
}
}
注意几点:
- 它只在
composer install或composer update解析依赖时检查,不会回溯已安装的包 - 如果
composer.lock里已经锁定了冲突版本,conflict不会自动删掉它——得先删 lock 文件再重装 - 范围写法必须合法,
" 有效,<code>"(带空格)会解析失败
最容易忽略的一点:改了 conflict 后不运行 composer update --lock,它就只是个 JSON 字段,不会产生任何实际约束。

















