应调process-timeout而非http.timeout,因Composer执行git clone时走系统命令而非HTTP协议栈;process-timeout控制子进程超时,默认300秒易触发硬杀,需设为1800秒并配合Git自身超时配置与残留清理。

卡在git clone时该调process-timeout,不是http.timeout
Composer遇到"type": "git"的包(比如dev-master或私有仓库),会调用系统git clone命令,这个过程完全不走HTTP协议栈,因此http.timeout或http-basic-timeout对它无效。真正起作用的是process-timeout——它控制所有外部子进程(包括git、unzip、php脚本)的单次执行上限。
-
process-timeout默认仅300秒,而国内直连GitHub常因DNS解析慢、TLS握手抖动、首字节延迟高,导致git clone卡在Resolving deltas或Receiving objects阶段 - 该超时是硬杀:一旦触发,
git进程被kill -9,残留的半截仓库目录(如vendor/some-vendor/some-package/.git/)会污染后续重试 - 注意:
process-timeout不是总耗时限制,而是每个子进程独立计时;一次composer install可能触发多次git clone,每次都会单独受控
怎么配才真正生效:全局 + 环境变量 + Git自身超时三重兜底
只改composer.json里的config.process-timeout没用——这个字段在Composer 2.x中已被忽略,必须走全局配置或环境变量。
仅从仓库的暂存文件生成 Git 提交消息。当用户要求 Codex 根据暂存更改、缓存差异、Git 索引或已通过 `git add` 添加的文件来编写、起草、创建或建议提交消息时使用;切勿代表用户执行提交操作。
- 全局写入(推荐开发机):
composer config -g process-timeout 1800(单位秒,建议1800即30分钟) - CI/CD中优先用环境变量:
COMPOSER_PROCESS_TIMEOUT=1800,它能覆盖插件和自定义installer启动的子进程 - Git自身也要设超时(防住Composer未覆盖的边界):
git config --global core.sshCommand "timeout 600 ssh"(Linux/macOS),或git config --global http.postBuffer 524288000防大包POST失败 - 若用HTTPS克隆,确保已配代理:
git config --global http.proxy http://127.0.0.1:7890,否则git clone会静默直连
为什么调了process-timeout还是卡住?先看-vvv最后一行
运行composer install -vvv,盯住输出的最后一行:
- 停在
Executing command (CWD: ...): git clone https://github.com/xxx→ 确认是git卡死,不是网络不通 - 如果最后是
Cloning into '...'后无进展,大概率是Git底层卡在DNS或TCP连接,此时process-timeout还没触发,得查git日志:git -c core.trace=1 clone https://github.com/xxx - 若报
fatal: unable to access 'https://github.com/xxx/': Failed to connect to github.com port 443 after 75004 ms: Connection refused,说明是代理或防火墙问题,不是超时配置问题 - 别忽略权限:私有GitLab/GitHub仓库若用SSH,
git clone会等SSH密钥密码输入,超时后直接中断;统一换HTTPS +github-oauthToken更稳定
中断后重试前必须清理残留,否则白调timeout
Composer没有断点续传,git clone中断后留下的破损目录会持续干扰:
- 不要
rm -rf vendor/——这会让autoload.php丢失,后续命令直接报错 - 精准清理:
rm -rf vendor/composer/installed.json vendor/composer/lock.json,再删掉对应包的目录(如rm -rf vendor/myorg/mylib) - 若
git clone中途生成了.git但没完成,进该目录手动rm -rf .git,否则Composer下次会尝试git pull而非重新clone - 最后清缓存:
composer clear-cache,避免从损坏的~/.composer/cache/vcs/里读取旧数据
vendor/子目录——它们不会自己消失,也不会被--prefer-dist跳过。

















