preferred-install 设为 source 后包仍走 dist,是因为该配置仅对新安装包生效,已缓存的 dist 包或包自身声明了 dist 且未禁用时 composer 不会切换;需清 vendor 和 lock 文件并确保未使用 --prefer-dist 才能验证效果。

为什么 preferred-install 设为 source 后包还是走 dist?
Composer 默认优先用 dist(压缩包),即使你全局或项目级设了 preferred-install 为 source,它也只在「安装新包时」生效;已缓存的 dist 包、或包本身声明了 "dist": {...} 且没禁用 dist,Composer 就不会切到 source。
实操建议:
- 删掉
vendor/和composer.lock,再运行composer install—— 这是验证配置是否起效最干净的方式 - 确认没有在命令行加
--prefer-dist(它会覆盖preferred-install) - 检查包的
composer.json是否含"dist"字段且未被"source"显式覆盖(部分私有包会强制 dist)
怎么全局设置 preferred-install 为 source?
全局设置影响所有后续项目,适合调试场景下统一走源码,方便直接改 vendor 里的代码、打断点、看 Git 历史。
执行这条命令即可:
composer config -g preferred-install source
注意:
- 该配置写入
~/.composer/config.json(macOS/Linux)或%APPDATA%\Composer\config.json(Windows) - 如果已有项目已写入本地
composer.json的"config"块,本地配置会覆盖全局,需手动删或改"preferred-install" - 设成
source后,composer update拉新版本也会走 git clone,首次耗时明显变长,尤其网络不稳定时容易卡在Cloning into...
preferred-install 支持哪些值?各有什么实际影响?
它不是布尔开关,而是按包类型匹配的策略映射,支持三种粒度:
-
"source":对所有包走git clone(前提是包提供"source"字段) -
"dist":强制走 zip/tar 下载(忽略source,适合离线或限速环境) -
{"my-vendor/*": "source", "*": "dist"}:按包命名空间分流,比如只对自家包走源码,第三方仍用 dist —— 这是最常用、最稳妥的调试策略
示例(写入项目 composer.json):
{
"config": {
"preferred-install": {
"acme/*": "source",
"my-org/*": "source",
"*": "dist"
}
}
}
这样既保调试效率,又避免把 monolog、symfony 等大包全 clone 下来拖慢 CI。
调试时发现 source 模式下 vendor 包没 .git 目录?
这是 Composer 5.0+ 的默认行为:即使走 source,也会在 clone 后执行 git clean -xdfq 并删掉 .git,防止污染项目 Git 状态。但调试需要历史和 diff,就得关掉这个清理。
加这个配置就行:
composer config --global discard-changes false
或者在项目 composer.json 里加:
{
"config": {
"discard-changes": false
}
}
注意:discard-changes=false 和 preferred-install=source 必须同时存在才有效;只设前者,dist 模式下依然没 .git。
另外,某些私有 Git 仓库若用了自签名证书或 SSH key 认证失败,source 模式会直接报 Failed to clone ... 错误,此时得先确保 git clone 手动能通,再让 Composer 走。










