Composer在代理切换后反复拉取旧Git提交,根本原因是vcs缓存目录中残留被代理污染的裸仓库快照,需手动删除对应裸仓库目录并同步清理repo缓存,否则Composer默认复用且不校验环境兼容性。

代理环境下composer install反复拉取旧 Git 提交?
不是网络超时,也不是 Git 配置错,而是 Composer 的 vcs/ 缓存目录里存着一个被代理污染的裸仓库快照——比如你切过公司内网代理(http-proxy),又切回直连,但 ~/.composer/cache/vcs/ 下的 git-bitbucket-org-xxx.git/ 仍保留着上次用代理 clone 出来的、不带最新 tag 的仓库,后续 install 就永远卡在旧 commit。
- 先确认是否真走 VCS:运行
composer show vendor/package -v,输出中若含source: git https://...,说明走的是 Git 拉取而非 dist ZIP - 查当前缓存路径:
composer config --global cache-dir,然后进vcs/子目录 - 按域名或包名模糊找对应裸仓库:
ls -d *github.com* *bitbucket.org* | grep -i vendor(Linux/macOS);Windows 可用Get-ChildItem "$env:APPDATA\Composer\Cache\Vcs" -Directory -Filter "*github*" - 直接删整个裸仓库目录(不是里面的内容),例如
rm -rf github.com-vendor-package.git—— 删对了,下次install就会重新 clone
http-proxy 切换后 vcs/ 缓存不自动失效?
Composer 不会因环境变量变更而主动丢弃已有 VCS 缓存。哪怕你已执行 composer config -g http-proxy "" 清掉代理,只要 vcs/ 下的目录还存在,它就默认复用,且不会校验该仓库是否与当前网络环境兼容。
- 代理切换后必须手动清
vcs/:Linux/macOS 运行rm -rf $(composer config --global cache-dir)/vcs/*;Windows PowerShell 用Remove-Item "$env:APPDATA\Composer\Cache\Vcs\*" -Recurse -Force - 别只删
files/或跑clear-cache—— 它们不影响 VCS 行为 - 如果项目依赖多个私有 Git 仓库,且部分需代理、部分直连,建议改用
git config --global url."https://".insteadOf "git@"+ SSH 密钥方式统一管理,绕过 HTTP 代理干扰
CI/CD 中并发构建导致 vcs/ 目录写冲突?
多个 Job 共享同一 COMPOSER_CACHE_DIR(如默认的 ~/.composer/cache)时,A Job 正往 vcs/github.com-xxx.git/objects/ 写对象,B Job 同时尝试 git fetch --tags,就会报 fatal: Unable to create '/path/to/.git/objects/...': Permission denied 或静默失败。
- 根本解法是隔离缓存路径:每个 Job 启动时设置独占缓存目录,例如 Linux CI 中加
export COMPOSER_CACHE_DIR="${CI_PROJECT_DIR}/.composer-cache" - 确保该路径在 Job 开始前为空,或至少不存在残留的
vcs/目录 —— 不要依赖clear-cache来清理,它不保证原子性 - Docker 构建中若用
root用户跑过composer install,后续非 root 用户无法删vcs/下属主为 root 的目录,得提前chown -R $USER:$USER ${COMPOSER_CACHE_DIR}
删了 vcs/ 还拉不到新 tag?
常见于私有 GitLab/GitHub Enterprise 仓库:本地 vcs/ 裸仓库删了,但远程仓库本身没推送新 tag,或者 Composer 解析时仍读取了 repo/ 下过期的 provider 映射,误判“该版本不存在”。
- 先确认远程确实有新 tag:
git ls-remote --tags https://your.gitlab.com/vendor/package.git - 再删元数据缓存:
rm -rf $(composer config --global cache-dir)/repo/https---your-gitlab-com(注意 URL 中/被转义为-) - 如果用的是自定义
repositories类型为composer(即私有 Packagist 镜像),确保该镜像服务本身已刷新源 —— Composer 不会主动通知上游更新 - 最后跑
composer update vendor/package --no-cache -vvv,日志里应出现Cloning into bare repository和Checking out ...,而非Using version x.x.x from cache
真正麻烦的是 vcs/ 和 repo/ 两处缓存的耦合关系——删一个不删另一个,问题只是延迟暴露。尤其在代理切换频繁、私有仓库权限变动、或 CI 环境用户混用的场景下,必须同步处理。











