必须用 --prefer-source 的情况包括:修改依赖源码、打临时补丁、调试底层逻辑,或 vendor 中只有 composer.json 而无 PHP 文件时;它强制 Git clone 替代下载 dist 包,但要求仓库支持克隆且有权限,私有包需配 SSH/token,CI 环境慎用。

什么时候必须用 --prefer-source
当你需要修改依赖包的源码、打临时补丁、调试底层逻辑,或者遇到 composer install 后 vendor 里只有 composer.json 没有实际 PHP 文件(常见于某些私有 Git 仓库配置了 "dist" 但没配好 "source")时,--prefer-source 是绕过 dist 包、强制走 Git clone 的最直接方式。
- Git 仓库必须支持 HTTPS/SSH 克隆,且当前机器有对应权限(比如私有仓库需配置 SSH key 或 token)
- 如果包只提供了
"dist"(zip/tar 包),加这个参数会报错:Failed to download xxx/xxx: No source defined for xxx/xxx - CI 环境慎用——它会让每次安装都重新 clone,比下载 dist 慢很多,还可能触发 Git 限流
--prefer-source 和 --prefer-dist 的行为差异
Composer 默认优先用 --prefer-dist:下载压缩包 + 校验 hash,快、轻量、适合生产;--prefer-source 则忽略 dist,直接 clone 仓库到 vendor/{vendor}/{package}/,并保留 .git 目录。
- 执行
composer install --prefer-source后,进任意 vendor 子目录,能直接git log或git checkout - 若已存在 dist 安装的包,该命令不会自动替换——得先
rm -rf vendor/{vendor}/{package}再重装 -
composer update默认行为不变,除非显式加--prefer-source,否则不会把 dist 换成 source
替代方案:局部对某个包强制 source
不想全局生效?可以在 composer.json 里为特定包指定 "source" 类型:
"require": {
"monolog/monolog": "^2.0"
},
"repositories": [
{
"type": "vcs",
"url": "https://github.com/Seldaek/monolog"
}
]
这样 composer require monolog/monolog 就会走 source;但注意:"repositories" 仅对未 packagist.org 托管的包或想覆盖默认源时才必要。
- 私有包常用写法:
"type": "git"+ 内网 Git 地址,配合--prefer-source确保 clone - 如果只是临时改一行代码,别忘了改完后
git add -f vendor/{...}—— 默认vendor/在 .gitignore 里
容易被忽略的副作用
--prefer-source 不是“更干净”的代名词,它会悄悄改变依赖的可复现性。
- 同一 commit hash 下,不同时间 clone 可能因 submodule 更新、.gitattributes 过滤规则变化导致文件内容不一致
- 某些包的
autoload规则依赖 dist 构建后的结构(比如生成的autoload_files.php),source 方式下可能缺失 -
composer.lock里记录的是 commit hash 而非 dist url + sha256,diff 时看起来像“版本没变”,实则源码可能已偏移
真要长期维护 patch,建议 fork + 提 PR,而不是靠本地 source+ 修改 vendor。










