镜像配置必须提交composer.json的repositories数组(首位为镜像对象、次位为{"packagist.org": false}),并删除vendor和composer.lock后重装;全局配置不进git,.composer/目录需清理。

镜像配置本身不进 Git,但它的生效依赖必须被正确提交和忽略——否则换源等于没换。
composer.json 里的 repositories 必须提交,且结构不能错
项目级镜像写在 composer.json 的 repositories 数组里,这是唯一能被 Git 跟踪、团队共享的配置方式。但它不是随便加个 URL 就行:
- 必须是数组,且镜像对象必须放在首位:
"repositories": [{"type": "composer", "url": "https://mirrors.aliyun.com/composer/"}, {"packagist.org": false}] -
{"packagist.org": false}是独立对象,不能合并进前面的镜像对象里,也不能写成"packagist": false - 如果用了私有源或 path repository,它们也得放在这同一个数组里,顺序决定优先级
- 改完后别只跑
composer update——它可能继续用旧的composer.lock里的官方 URL,必须删掉vendor/和composer.lock再跑composer install
全局镜像配置(~/.composer/config.json)不能进 Git
~/.composer/ 是用户级目录,路径类似 /home/username/.composer/ 或 C:\Users\Name\AppData\Roaming\Composer\,它不属于项目,也不该出现在项目 Git 里。常见误操作:
- 在项目根目录下执行
composer config --global repo.packagist ...,结果把全局配置写进了当前目录(生成了.composer/子目录) - 用
composer create-project初始化时,模板脚本错误地把~/.composer/config.json复制进了项目 - 一旦发现项目里有
.composer/目录,立刻git rm -r --cached .composer并提交清理
vendor/ 和 composer.lock 的忽略与提交边界必须清晰
镜像是否生效,最终体现在 composer install 能否成功下载包。而这个过程高度依赖 .gitignore 和 Git 状态的一致性:
-
vendor/必须写进.gitignore,推荐写法是/vendor(开头斜杠,无尾部斜杠),避免匹配到myvendor.php这类文件 -
composer.lock必须提交——它记录了从哪个源、哪个 URL 下载的每个包,镜像配置改了但 lock 没更新,composer install仍会去连 packagist.org - 已误提交过
vendor/?光改.gitignore不够,必须执行git rm -r --cached vendor,否则 Git 依然跟踪它 - CI 流水线里若缓存了旧
composer.lock,哪怕镜像已配好,也会 fallback 到官方源;建议加rm -f composer.lock && composer install或清缓存
为什么改了镜像还连 packagist.org?大概率是 fallback 没关死
Composer 2.x+ 默认开启 fallback:镜像返回 404 或超时,它会自动重试 packagist.org。这不是 bug,是设计行为。要彻底关掉:
- 项目级:确保
repositories数组里有且仅有{"packagist.org": false}这个独立对象 - 全局级:
composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/中的composertype 不可省略,URL 必须以/结尾 - 验证是否生效:
composer config -g repo.packagist应输出完整 JSON,不是空或null;composer install -vvv可看实际请求的 URL - 别信“我改了就一定生效”——删
vendor/和composer.lock是硬性前置动作,跳过等于白配
最常被忽略的点是:镜像配置只是告诉 Composer “去哪找”,而 composer.lock 才真正决定“实际从哪下”。两者不同步,换源就只是自我安慰。











