composer install 仍走 git clone 缓存是因为它复用 vendor/ 和 ~/.composer/cache/vcs/ 中的 git 镜像,--no-cache 仅禁用元数据缓存而非源码副本;强制更新需清镜像、设 composer_cache_dir=/dev/null 或改用 dist 模式。

composer install 为什么还是走 git clone 缓存
因为 composer install 默认不会跳过已有的 vendor 和 .git 目录缓存,哪怕加了 --no-cache,它只影响 Composer 的内部包元数据缓存(比如 packages.json),不清理 Git 克隆下来的源码副本。
常见错误现象:改了 repositories 指向私有 Git 分支,composer install --no-cache 后 vendor 里仍是旧 commit —— 实际上 Composer 复用了之前 git clone 出来的本地工作副本,根本没重新拉。
-
--no-cache只禁用 HTTP 层和 packagist.org 元数据缓存,不影响vendor/目录或~/.composer/cache/vcs/下的 Git 镜像 - 真正触发重新 clone 的是「目标目录不存在」或「Git remote URL / reference 发生变化」
- 如果只是想强制更新某一个包,
composer update vendor/package --with-dependencies更可靠,它会校验 lock 文件与远程 HEAD
如何真正绕过 git clone 缓存(VCS 镜像)
Composer 在 ~/.composer/cache/vcs/ 下维护 Git 仓库镜像(mirror),每次 install/update 都优先复用。要跳过它,得从源头切断镜像读取路径或清空对应缓存项。
- 临时禁用 VCS 缓存:设置环境变量
COMPOSER_CACHE_DIR=/dev/null(Linux/macOS)或set COMPOSER_CACHE_DIR=NUL(Windows),再运行composer install - 手动清理特定包镜像:
rm -rf ~/.composer/cache/vcs/https---github.com-vendor-package.git/(路径按实际 URL 转义) - 用
composer clear-cache清掉整个缓存,但注意这也会清掉下载的 zip 包,下次安装可能变慢 - 在
composer.json中为包显式指定"dist"而非"source",例如:{"type": "package","package": {"name": "vendor/pkg","version": "dev-main","dist": {"url": "https://example.com/pkg.zip","type": "zip"}}—— 这样就完全绕开 git clone
composer create-project --no-cache 不生效的真相
create-project 的 --no-cache 同样只跳过元数据缓存,不阻止它从 ~/.composer/cache/vcs/ 拉镜像、解压、再 git checkout。尤其当你反复用相同包名创建项目时,几乎必然复用旧镜像。
- 最稳妥做法:加
--remove-vcs(删掉 .git 目录),再配合rm -rf ~/.composer/cache/vcs/*彻底清镜像 - 若用的是 GitHub/GitLab,可改用
dist模式:在composer.json的repositories里把"type": "vcs"改成"type": "package"并提供"dist"字段 - CI 场景下建议直接设
COMPOSER_CACHE_DIR=/tmp/composer-cache并在 job 结尾rm -rf /tmp/composer-cache,避免跨任务污染
为什么 vendor 下的包仍有 .git 目录
因为 Composer 默认以 source 方式安装开发版包(dev- 开头的版本),即执行 git clone 到 vendor 里。这不是 bug,是设计行为——方便你直接改代码、提交 PR。
- 想彻底禁掉 .git:在
composer.json加"prefer-dist": true,但前提是包本身提供了 dist 发布(GitHub Release / zip 包) - 某些私有包没配 dist,即使写了
"prefer-dist": true,Composer 仍 fallback 到 source,此时唯一办法是自己打包 zip 并在repositories里声明"dist" - 检查是否真用了 source:看
vendor/vendor/package/.git/config里的url,和composer show vendor/package输出的source行一致
真正难处理的是混合场景:一部分包走 dist,一部分必须走 source,而你只想对其中某个包跳过 git clone —— 这时候就得单独拎出来用 package 类型定义,其他保持默认。细节容易漏,尤其是 URL 转义和 commit hash 校验。










