Composer离线使用VCS缓存需满足三重条件:路径存在、权限正确、分支匹配,且必须预热(联网执行--prefer-source)、配置"prefer-source":true,并确保repositories正确声明vcs类型。

离线环境无法拉取 Git 仓库时,Composer 会尝试复用 vcs 缓存里的本地 Git 克隆副本——但这个行为不是默认“自动生效”的,必须满足路径、权限、分支匹配三重条件。
确认 vcs 缓存是否真实存在且可用
Composer 的 VCS 缓存位于 ~/.composer/cache/vcs/(Linux/macOS)或 %APPDATA%\Composer\Cache\vcs\(Windows),它不是简单存 ZIP,而是完整 git clone --mirror 的裸仓库。运行以下命令验证:
- 查缓存根路径:
composer config --global cache-dir,再进vcs/子目录看有没有对应 URL 的哈希目录 - 进该目录后执行
git show-ref --heads,确认目标分支(如dev-main)的 commit hash 是否存在 - 若目录为空或报
fatal: not a git repository,说明缓存根本没建立过,离线时必然失败
离线时强制走 vcs 缓存的必要配置
仅靠缓存存在还不够。Composer 默认优先走 dist 包(.zip),除非你显式禁用或让 dist 不可用。需在 composer.json 中设置:
- 删掉或注释掉
"prefer-stable": true和"minimum-stability": "stable"—— 它们会压制 dev 分支解析 - 加
"prefer-source": true,强制 Composer 用git clone方式安装,此时才会查vcs/缓存 - 确保
require中版本约束匹配缓存里的分支名,例如写"dev-main"就要求缓存里有refs/heads/main,而不是master
离线前必须完成的预热动作
缓存不是“用了就留”,而是“首次成功 clone 后才存”。所以离线前必须联网完成一次完整流程:
- 在联网机器上,对目标私有包执行一次
composer update vendor/package --prefer-source -v,日志里看到Cloning [url] to /path/to/cache/vcs/xxx才算落盘 - 手动验证缓存完整性:
cd ~/.composer/cache/vcs/[hash]/→git ls-remote origin应返回非空分支列表 - 把整个
~/.composer/cache/vcs/目录打包,同步到离线机器对应路径(注意保持用户权限一致,否则git操作会因权限拒绝而 fallback 到网络)
常见失效原因和绕过方式
即使缓存存在,离线时仍报 Failed to clone ... repository not found,大概率是以下之一:
-
composer.json里repositories配置被忽略:检查是否含空对象{}或类型拼错(如写成"type": "git"而非"type": "vcs") - Git URL 协议不一致:缓存里存的是
https://,但composer.json写了git@,会导致哈希不匹配,直接跳过缓存 - 离线机器没装
git命令:Composer 依赖系统git执行archive,哪怕只读缓存也需二进制可用 - 想省事直接复制
vendor/?不行。vcs 缓存只影响下载阶段,vendor/是安装产物,与缓存无关;且 symlink 或 classmap 不会自动适配新环境
真正可靠的离线方案,从来不是赌缓存能用,而是提前用 satis build 生成静态 packages.json + dist/ ZIP,彻底绕开 Git 和 vcs 层。缓存只是临时补救手段,一旦分支更新、URL 变更或权限变动,就容易断在最不该断的地方。


















