必须加 --prefer-source 的场景有五种:需在 vendor 中直接调试、fork 后指向特定 commit、依赖未发正式 tag 且 zip 缺失生成文件、ci 中需 patch 且工具要求 .git 目录、私有包仅支持 source 安装。

用 --prefer-source 安装包,本质是让 Composer 克隆 Git 仓库而非下载 ZIP 归档,适用于需要修改依赖源码、调试、打补丁或确保使用特定 commit 的场景;但默认不推荐日常使用,它会显著拖慢安装速度、占用更多磁盘空间,且可能因网络或权限问题失败。
什么时候必须加 --prefer-source
你遇到以下情况之一时才该考虑它:
- 要直接在
vendor/下的某个包里加var_dump或断点调试,而该包没提供可调试的 dev 分支或autoload-dev配置 - 你 fork 了某个包,改了代码,想通过
"package-name": "dev-main#abc123"指向自己的 fork + 特定 commit,并确保本地能直接编辑 - 依赖的包没有发布正式 tag(比如只在
dev-master上开发),且你发现 ZIP 包里缺失某些生成文件(如src/下的类被构建脚本生成,但 ZIP 未包含) - CI 环境中需对依赖做 patch(例如用
cweagans/composer-patches),而某些 patch 工具要求源码存在 .git 目录
--prefer-source 和 --prefer-dist 的实际区别
两者不是“功能不同”,而是“获取方式不同”:
-
--prefer-dist(默认):从 Packagist 缓存或 GitHub Releases 下载预打包的.zip或.tar.gz,解压即用,快、轻、稳定 -
--prefer-source:执行git clone --no-checkout <repo-url></repo-url>,再git checkout <commit-hash></commit-hash>,保留完整 Git 历史和 .git 目录 - 注意:
--prefer-source不等于 “安装开发版”——composer require vendor/name:dev-main才指定版本,--prefer-source只管怎么拉代码 - 如果包没配置
source信息(比如私有包没设repositories或 type 不是vcs),--prefer-source会直接报错:Could not fetch source code...
如何安全启用并避免踩坑
别全局设置,按需临时加参数最可控:
- 单次安装:运行
composer install --prefer-source或composer require vendor/name --prefer-source - 项目级默认(不推荐):在
composer.json里加"config": { "preferred-install": "source" },但所有包都会走 git clone,包括monolog/monolog这种大包,CI 构建时间可能翻倍 - 排除干扰:若只想对某几个包用 source,其他仍走 dist,得配合
repositories自定义源,并确保其 type 为vcs,否则 Composer 会忽略--prefer-source - 权限陷阱:某些内网 Git 服务(如 Gitee 私有库、自建 GitLab)要求 SSH key 或 token,
--prefer-source会触发 Git 认证,而--prefer-dist走 HTTPS 下载可能反而更顺
源码安装后要注意什么
一旦用了 --prefer-source,vendor/ 下的包就变成真实 Git 工作区:
- 别手动
git checkout切分支——下次composer update会强制重置到锁定的 commit - 想保留修改?必须先
git stash或提交到新分支,否则composer update会丢掉改动 -
composer update vendor/name仍会重新git fetch && git checkout,不会 merge 你的本地变更 - 检查是否生效:进
vendor/vendor-name/package-name,运行git rev-parse HEAD,输出应为一串 commit hash;若报错Not a git repository,说明没走 source 流程
真正难的不是加参数,而是判断“此刻我是不是真的需要它”。多数调试需求靠 Xdebug + IDE 断点就够了,强行 source 只会让 vendor/ 变成一堆难以维护的 Git 垃圾。如果只是想改依赖,优先考虑 path repository 或 fork + repositories 替换。











