--dry-run是Composer完整执行依赖解析但跳过文件写入的真模拟,能精确预览install/update/remove操作及版本变更;不加-v则关键风险不可见,上线前必须使用。

直接说结论:--dry-run 不是“看看而已”,它是 Composer 完整走完依赖求解逻辑、只跳过写文件的真模拟;不用 -v 就等于没用,上线前跳过它大概率翻车。
composer update --dry-run 真实行为是什么
它不是打印个列表就完事。Composer 会真实读取 composer.json 和 composer.lock,重新执行全部约束解析、版本回溯、冲突调解,算出每一项要 install / update / remove 的包和精确版本号,最后停在「准备写入」那一步——不改 vendor/、不重写 composer.lock、不重建 autoloader。
这意味着你能看到:
- Updating monolog/monolog (2.9.1 => 3.0.0) → 主版本跃迁,BC break 风险高
- Downgrading symfony/console (6.4.0 => 5.4.33) → 因某个新依赖要求 PHP 8.0,而你锁了 PHP 8.1,结果倒推降级
- Installing laravel/envoy (v2.0.0) → 新增包,但你项目里根本没用到,得确认是不是间接引入
哪些命令支持 --dry-run
别只盯着 update。所有会改变项目状态的命令都支持:
-
composer require monolog/monolog:^3.0 --dry-run→ 看新增依赖会不会把现有psr/log从 v2 强制升到 v3 -
composer remove guzzlehttp/guzzle --dry-run→ 发现laravel/framework强依赖它,会连带卸载整个laravel生态 -
composer install --dry-run→ 检查当前composer.lock是否还能在本机环境满足(比如提示ext-igbinary is required但你没装)
为什么必须加 -v 才算真正用了 --dry-run
默认输出太简略,关键风险全被藏起来了。加 -v 后你会看到:
- 哪条
conflict规则被触发,导致某包被迫降级 - 哪个包的
require约束和你的 PHP 版本不兼容,从而选了更老的候选版本 - 自定义
repositories中的包是否能正常解析元数据(网络失败时这里会卡住)
常见错误:composer update --dry-run 输出干净,一跑真实 update 就报 Class not found。加 -v 后才发现 symfony/event-dispatcher 被悄悄从 v6 降到了 v5.4,而你的代码用了 v6 的 StoppableEventInterface。
--dry-run 看不见的三类问题,得人工盯
它再准也只是模拟 Composer 自身流程,以下必须手动核对:
- 网络与权限:
--dry-run会访问 Packagist 或私有源,但不验证 token 是否有效、代理是否放行、vendor/目录是否可写 - PHP 运行时:
"php": "^8.1"满足,但你开了opcache.enable=1且没清缓存,新类加载失败不会被预警 - autoload 配置:
PSR-4映射漏了一层目录、files加载的函数被删了但没报错——这些只有vendor/autoload.php真生成后才能暴露
真正稳的流程是:composer update --dry-run -v → 扫一眼有没有 major 升级和非预期 downgrade → 检查私有源凭证和 PHP 扩展 → 清 opcache → 再执行真实 update。


















