必须用--prefer-source才能在vendor中改代码、看git blame、切分支;但需包提供source字段,且配合--keep-vcs或composer_discard_changes=0保留.git目录,否则默认不存仓库。

想在 vendor 里直接改依赖代码、看 git blame、切分支打补丁?必须用 --prefer-source,但光加参数不等于成功——它只在包本身提供有效 source 字段时才真正克隆 Git 仓库。
为什么 composer install --prefer-source 有时没效果?
常见错误现象:命令跑完,进 vendor/foo/bar 目录,ls -a 看不到 .git;git status 报错 “not a git repository”。
- 包作者没在
composer.json里写"source"字段(只写了"dist"),Composer 就会静默 fallback 到 zip 包,不报错也不提醒 - 你之前装过这个包(
vendor已存在),而--prefer-source对已安装包默认跳过,不会重拉 - 网络问题导致
git clone失败(比如被墙、私有仓库鉴权失败),Composer 自动降级走 dist,日志里只有一句Cloning failed, falling back to dist - 即使克隆成功,Composer 默认执行
git clone --no-checkout+git checkout -qf <commit></commit>,然后删掉.git目录——所以你看到的是干净代码,不是完整仓库
怎么确认 --prefer-source 真生效了?
别只信命令输出,进目录验证才是关键。操作顺序不能乱:
- 先确保
vendor/foo/bar目录不存在(或整个vendor清空),再运行composer install --prefer-source - 进
vendor/foo/bar,执行git remote -v:如果输出类似origin https://github.com/foo/bar.git (fetch),说明是克隆来的 - 执行
ls -a | grep git:必须看到.git才算保留了仓库;若没有,得加--keep-vcs - 执行
composer show foo/bar --all,检查输出中source行是否非空,且 URL 可curl -I或git ls-remote验证
如何强制保留 .git 目录并支持本地提交?
--prefer-source 默认不保留 .git,这是 Composer 的安全策略(防部署污染)。要真能 git commit,必须组合使用:
- 加
--keep-vcs参数:composer install --prefer-source --keep-vcs(Composer 2.2+ 支持) - 或者设环境变量:
COMPOSER_DISCARD_CHANGES=0,再跑命令(兼容旧版) - 进目录后立刻
git status:应显示 clean;git log -n 1的 hash 要和composer show输出的source.reference一致 - 如果要长期修改,别直接在
vendor提交——先git remote set-url origin git@github.com:yourname/bar.git换成可写地址,再改、再 push
只想对某一个包用源码,其他保持 dist 怎么办?
全局 --prefer-source 会影响所有包,容易拖慢 CI 和占磁盘。精准控制更稳妥:
- 在
composer.json的repositories段手动加一条vcs类型源:{ "repositories": [ { "type": "vcs", "url": "https://github.com/Seldaek/monolog" } ] } - 这条配置会让 Composer 自动对该包走
source安装,哪怕你没加任何--prefer-source - 然后只更新这个包:
composer update monolog/monolog,其他包不受影响 - 注意:如果该包在 Packagist 上的版本 tag 和你
url仓库里不一致,Composer 会报Could not find package,此时得加"no-api": true或改用package类型显式声明版本
最常被忽略的一点:即使你成功克隆了带 .git 的包,下次 composer update 仍会按 composer.lock 里的 commit hash 强制重置工作区——临时改代码可以,但长期 fork 或打补丁,必须用 path 仓库或 repositories + 自己的分支,否则改完就丢。











