必须手动清理vcs/和repo/下对应缓存目录:先按URL哈希定位vcs/https---github.com-org-repo.git等子路径并删除,再删repo/对应元数据及vendor/composer/installed.json,最后用--no-cache强制重拉。

改了 VCS 源(比如 Git URL 或分支名)后 composer update 仍拉旧提交?不是配置没生效,是缓存里还存着旧仓库的裸克隆和元数据快照,必须手动清掉 vcs/ 和 repo/ 下对应目录。
为什么 composer clear-cache 不够用?
它会删 files/ 和 vcs/,但只清 vcs/ 的顶层目录,而 Composer 实际把每个 Git 仓库的裸克隆存在 vcs/https---github.com-vendor-package.git/ 这类子路径下——clear-cache 并不递归清理这些子目录,旧 clone 仍在后台被复用。
- 现象:改了
"url": "git@github.com:old-org/pkg.git"为新地址,composer update却仍从 old-org 拉代码 - 原因:Composer 检测到
vcs/下已有同名仓库(按 URL hash 命名),就跳过重新 clone,直接用旧快照 - 更隐蔽的是:如果只是改了分支(如
"dev-main"→"dev-next"),它甚至不会触发重新解析,因为源地址没变
精准定位并删除旧 VCS 缓存目录
别全删 vcs/——除非你确定所有项目都换源了。优先按 URL hash 找准目标:
- 先查当前项目用的源:
composer show vendor/package -v,看输出里source行的 URL - 把 URL 转成缓存路径:去掉协议头、替换
/为-、去掉末尾.git;例如https://github.com/myorg/pkg.git→https---github.com-myorg-pkg - 进缓存目录:
ls -d $(composer config --global cache-dir)/vcs/*$(echo "https---github.com-myorg-pkg" | sed 's/[^a-zA-Z0-9-]//g')*(Linux/macOS) - Windows 用户可用:
Get-ChildItem "$env:APPDATA\Composer\Cache\vcs" -Filter "*myorg*pkg*" - 确认无误后直接
rm -rf或Remove-Item -Recurse对应目录
同步清理 repo 元数据和 vendor 状态
VCS 源变更后,Composer 仍可能从旧 packages.json 里读版本列表,或继续用 vendor/composer/installed.json 里的旧 commit hash:
- 删 repo 快照:
rm -rf $(composer config --global cache-dir)/repo/https---github.com-myorg-pkg(路径规则同上) - 删本地安装记录:
rm -f vendor/composer/installed.json(否则composer show仍显示旧 commit) - 加
--no-cache强制重走完整流程:composer update vendor/package --no-cache -v,日志里应出现Cloning into bare repository或Downloading ...zip
CI/CD 或 Docker 构建时最容易漏的点
自动构建环境常因用户权限或缓存路径错位导致清理失效:
- 用
root跑过composer install,后续非 root 用户执行rm -rf会被拒绝——加sudo或统一用同一用户 -
COMPOSER_CACHE_DIR在构建脚本中未export,composer config --global cache-dir返回空值,删的其实是空路径 - Docker 多阶段构建中,
vcs/目录若挂载为 volume,旧缓存会跨构建残留——应在RUN阶段内完成清理,而非依赖宿主机 - 改了 VCS 源却没动
composer.lock,里面仍锁着旧source.reference——删 lock 文件或手动编辑它,否则update不会更新 commit hash
VCS 源改完不光是 URL 变,它的整个生命周期(clone、fetch、checkout)都依赖缓存路径的精确匹配。删错一级目录,就可能让 Composer 在“新 URL”和“旧裸库”之间反复横跳,最后装上的还是你以为已经废弃的提交。











