答案是因Composer复用composer.lock中dist哈希及vendor目录存在,跳过VCS重建;需删vendor下对应包、移除lock中条目,再执行composer update vendor/package --no-cache --with-all-dependencies触发裸仓库重拉。

Composer VCS 缓存被删后为什么 vendor 里还缺包?
因为 Composer 的 VCS 缓存(~/.composer/cache/vcs/)不只是“加速用的临时文件”,它是 Git 克隆的裸仓库(bare repo),composer install 或 update 时若发现该目录下已有对应 URL 的裸仓库,就会直接 git archive 导出,跳过网络拉取。一旦你手动删了它,又没触发重装逻辑,vendor 目录就卡在“已安装但内容不全”的状态——尤其对 "type": "vcs" 或通过 Git URL require 的包(如 "monolog/monolog": "dev-main#abc123")。
怎么精准重建缺失的 VCS 裸仓库?
别跑 composer clear-cache,它不重建 vcs/;也别删整个 cache/,那会连其他源一起干掉。正确做法是让 Composer 主动重拉并重建:
- 先确认目标包是否真走 VCS:运行
composer show vendor/package-name,看source字段是不是vcs https://...或git ... - 删掉 vendor 下对应目录:
rm -rf vendor/vendor/package-name(只删这一个,不动其他) - 删掉 composer.lock 中该包的条目(或整删
composer.lock,否则 update 可能跳过) - 执行
composer update vendor/package-name --no-cache --with-all-dependencies——--no-cache强制绕过 files/ ZIP,--with-all-dependencies确保子依赖也走 VCS 拉取
执行过程中,你会看到类似 Cloning https://github.com/... into /home/user/.composer/cache/vcs/https---github.com-vendor-package.git 的日志,说明裸仓库正在重建。
Windows 用户特别注意权限和路径
PowerShell 下 composer config --global cache-dir 返回的路径带换行或空格,直接拼接会失败。安全写法是:
Remove-Item "$env:APPDATA\Composer\Cache\vcs\https---github.com-vendor-package.git" -Recurse -Force
然后运行 composer update 即可。别用资源管理器手动删 vcs/ 子目录——Windows 文件锁常导致删不干净,后续 git clone 会静默失败。
为什么删了 vcs/ 后 composer install 还不重建?
根本原因是 composer install 默认复用 composer.lock 里的 source.reference 和 dist.sha256,只要 vendor/ 下目录存在、且哈希匹配,它就不碰 vcs/。所以必须打破这个闭环:
-
composer.lock里该包的source字段必须是vcs类型,不是dist;如果之前是 dist 安装的,现在想切回 vcs,得先composer remove vendor/package-name再require带 Git URL 的版本 - 确保项目
composer.json的repositories正确声明了该 VCS 源,否则 Composer 根本不会尝试去git clone - PHP 进程需有写入
~/.composer/cache/vcs/的权限,CentOS 上常见于用sudo composer创建缓存后,普通用户无法覆盖
最顽固的情况:vcs/ 目录被删,但 vendor/ 下残留了一个 symlink 指向已不存在的裸仓库路径——此时要先 ls -la vendor/vendor/package-name 确认,再手动 rm 掉 symlink。


















