Composer 不会自动将 Git 克隆副本存入 cache-dir 下的 vcs/ 子目录,必须显式执行 composer config --global cache-vcs-dir 设置绝对路径,并手动创建目录、配置权限,否则静默回退至默认路径。

composer config --global cache-vcs-dir 必须显式设置
Composer 不会自动把 Git 克隆副本(VCS 缓存)放到 cache-dir 下的 vcs/ 子目录里,除非你明确告诉它——cache-vcs-dir 是独立配置项。只设 cache-dir,VCS 缓存仍走默认路径,导致多项目间无法共享 Git 仓库副本,反复 clone 耗时又占空间。
正确做法是单独执行:
composer config --global cache-vcs-dir /mnt/shared-vcs
注意:cache-vcs-dir 的值必须是**绝对路径**,不能含 ~ 或 $HOME;末尾不加 /vcs,Composer 会自己在该路径下建 vcs/ 目录(不是拼成 /mnt/shared-vcs/vcs/vcs)。
- Linux/macOS/WSL:直接写完整路径,如
/data/composer-vcs - Windows CMD:用英文双引号包裹,含空格或反斜杠时必须加,如
"D:\composer-vcs" - PowerShell:避免直接写
%APPDATA%,先用$env:APPDATA获取再拼接,否则可能写入失败
目录必须手动创建且权限匹配当前运行用户
Composer 从不自动创建 cache-vcs-dir 指向的目录,也不会报错提示“目录不存在”。如果路径未建或权限不足,它会静默 fallback 到默认位置(~/.composer/cache/vcs 或 %APPDATA%\Composer\Cache\vcs),你以为改了,其实没生效。
操作顺序不能颠倒:
- 先执行
composer config --global cache-vcs-dir /path/to/vcs - 再手动创建目录:
mkdir -p /path/to/vcs(Linux/macOS)或资源管理器新建对应文件夹(Windows) - 设权限:
chmod 755 /path/to/vcs(Linux/macOS);Windows 需右键 → 属性 → 安全 → 确保当前用户有“完全控制” - CI/Docker 场景下尤其注意:若用
root执行 config,但实际以www-data运行 Composer,则需chown www-data:www-data /path/to/vcs
验证是否真在用新 VCS 缓存路径
composer config --global cache-vcs-dir 只显示你“写了什么”,不代表 Composer “用了什么”。真正生效路径得看 composer diag 输出里的 VCS directory: 行。
更可靠的验证方式:
- 运行
composer clear-cache,观察日志中清理的是不是你设的新路径下的vcs/目录 - 执行
composer update -vvv,搜日志中Cloning [repo] into cache或Using cached version of对应的路径 - 检查环境变量:
echo $COMPOSER_CACHE_DIR(Linux/macOS)或echo %COMPOSER_CACHE_DIR%(Windows)。如果这个变量被设了,它会**覆盖所有 config 配置**,包括cache-vcs-dir
cache-read-only true 时,vcs 目录必须可读且非空
启用只读缓存(composer config --global cache-read-only true)后,Composer 不会尝试写入 vcs/ 目录,但它仍会从中读取已有的克隆副本。如果新 cache-vcs-dir 下没有历史克隆,而你又开了 cache-read-only,Composer 就会卡住或报错“Could not clone …”,因为它既不能读(空目录),也不能写(只读限制)。
所以开启 cache-read-only 前,务必确保:
-
vcs/目录下已有至少一个成功克隆的仓库(比如先关掉只读跑一次composer install) - 该目录对当前用户是可读的(
chmod 555或 Windows 上“只读”属性 ≠ 系统级只读权限) - 不要误删
vcs/下的.git子目录——那是克隆副本的核心,删了就等于白配
最易忽略的一点:VCS 缓存路径变更后,旧项目不会自动迁移已有的克隆副本。你得手动把老 ~/.composer/cache/vcs/ 下的对应目录复制过去,否则首次 update 仍会重新 clone。











