根本原因是Composer复用~/.composer/cache/vcs/中旧的Git裸仓库缓存,该缓存不校验远端URL变更或SSH配置更新,导致克隆卡住;需手动清空缓存并验证Git连通性、URL一致性及SSH权限。

SSH访问VCS仓库时,为什么composer update仍卡在克隆阶段?
根本不是SSH密钥没配好,而是Composer复用了~/.composer/cache/vcs/里旧的Git裸仓库快照——哪怕你刚改了url字段或切换了SSH key,它也照用不误。这个缓存目录不会自动校验远端变更,更不会感知SSH配置更新。
- 运行
composer show vendor/package,若输出里source显示git而非path或dist,说明确实在走VCS拉取 - 加
-vvv参数执行composer update vendor/package,日志中出现Cloning into bare repository后长时间停住,基本可断定是缓存里的裸仓库损坏或权限失效 - 检查
~/.composer/cache/vcs/下对应URL哈希目录的config文件,确认url值是否仍是旧的git@github.com:xxx(比如从git@github.com换成了git@gitlab.com,但缓存没清)
rm -rf ~/.composer/cache/vcs/*之后还连不上SSH怎么办?
清空vcs/只是第一步。Composer下次拉取时会重新git clone --mirror,但这个过程完全依赖系统级Git行为——它不会读composer.json里的repositories配置去重试,也不会帮你解SSH密钥密码。
- 手动测试Git连通性:
git ls-remote git@github.com:your-org/your-repo.git HEAD,失败则说明SSH本身不通(如~/.ssh/config未配别名、agent未加载key、权限为600但属主不对) - 确保
url字段用的是完整SSH格式,不能混用HTTPS:"url": "git@github.com:your-org/your-repo.git",而不是"url": "https://github.com/your-org/your-repo" - 如果项目用Docker或CI,必须挂载
~/.ssh目录并设置SSH_AUTH_SOCK环境变量;否则git clone会因找不到agent而卡死
如何让SSH VCS仓库真正复用缓存?
缓存能复用的前提是:两次请求的Git URL完全一致,且远程仓库的HEAD没有变。但SSH URL看似相同,实际可能因~/.ssh/config别名解析不同而指向不同主机——Composer无法感知这种间接映射,导致生成不同哈希缓存目录。
- 避免用SSH别名,直接写真实域名:
"url": "git@github.com:org/repo.git",而非"url": "git@gh:org/repo.git"(即使~/.ssh/config里定义了Host gh) - 强制统一协议和端口:若自建Git服务器用了非标端口(如
git@192.168.1.100:2222:/repo.git),务必在url中显式写出:2222,否则缓存哈希会因默认端口:22而错配 - 镜像源配置对SSH VCS无效:
composer config -g repo.packagist只影响Packagist包,不要试图把它设成SSH地址——那会导致所有公共包拉取失败
本地改了私有包代码,composer update却不生效?
这不是缓存问题,是VCS模式本身的限制:Composer把SSH仓库当“远程源”处理,它只认Git commit hash,不监听工作区文件变更。你改完代码不git commit,它永远拉不到新内容。
- 每次修改后必须
git add . && git commit -m "dev",再git push到远端(哪怕是git@localhost) - 如果想跳过commit直接测试,改用
path仓库模式,但要同步删掉vcs缓存+vendor/下的symlink+重跑composer dump-autoload - CI环境中禁用
path,因为构建机通常没权限访问本地路径;此时唯一可靠方式是打tag(如v1.2.3)并require该tag,再git push --tags


















