repositories必须是composer.json顶层字段,每项须显式声明"type": "vcs"且url以.git结尾;需禁用packagist.org并确保域名、包名、认证与git tag严格一致。

repositories 必须是顶层字段,且每项显式声明 "type": "vcs"
Composer 不会扫描嵌套结构或默认推断类型——repositories 只能在 composer.json 顶层出现,且每一项都必须带 "type": "vcs"。漏掉这行,整个仓库条目会被静默忽略。
常见错误包括:
- 把
repositories写在config或require里 - 写成
"type": "git"或"type": "package"(只有"vcs"才触发 Git 克隆) - URL 不以
.git结尾,例如写成https://gitlab.example.com/acme/utils,实际应为https://gitlab.example.com/acme/utils.git
正确示例:
{
"repositories": [
{
"type": "vcs",
"url": "https://gitlab.example.com/acme/utils.git"
}
],
"require": {
"acme/utils": "^2.1"
}
}
私有 Git 仓库的 URL 必须可直接 git clone
Composer 内部调用的是 git clone 命令,所以你填的 URL 必须能被系统原生执行成功。不能是网页地址,也不能依赖浏览器登录态。
推荐用法:
- HTTPS 方式:搭配
auth.json使用 token 认证,URL 形如https://gitlab.example.com/acme/utils.git - SSH 方式:URL 形如
git@gitlab.example.com:acme/utils.git,需确保运行composer install的用户已配置 SSH key 且ssh -T git@gitlab.example.com能通
注意:Bitbucket 必须用 HTTPS + App Password;GitLab 推荐用 Personal Access Token 并勾选 read_repository;GitHub 同理,token 需含 repo 权限。
必须禁用 packagist.org,否则私有包永远不会被匹配
即使你写了正确的 repositories 和 require,只要没关掉默认源,Composer 就永远先查 packagist.org,查不到才 fallback——而 fallback 不会尝试解析你定义的 vcs 地址,只会报 Could not find package。
解决方法是在 repositories 数组开头或结尾加一项:
{
"packagist.org": false
}
注意两点:
- 这一项也必须是
repositories数组中的一条对象,不是布尔值 - 键名必须是字符串
"packagist.org",不能写成"https://packagist.org"或漏掉.org
Satis 类型私有源要配 "type": "composer",且 URL 必须带末尾斜杠
如果你用 Satis、Artifactory 或 Private Packagist 这类托管服务,它们提供的是静态 packages.json 接口,不是 Git 仓库,这时 type 必须是 "composer",不是 "vcs"。
关键细节:
- URL 必须以
/结尾,例如"https://packages.internal/",少这个斜杠会导致 Composer 请求packages.json时 404 - 该源只负责提供元数据,不参与 Git 克隆;真正拉代码还是靠目标仓库自身的
dist或source配置 - 仍需配合
{"packagist.org": false},否则它只是个低优先级 fallback
这种配置下,composer.json 的 repositories 看起来像这样:
{
"repositories": [
{ "packagist.org": false },
{
"type": "composer",
"url": "https://packages.internal/"
}
]
}
真正的难点不在写对格式,而在于所有环节的域名、包名、认证凭据、Git Tag 规范必须完全对齐——差一个字符,就卡在 No valid composer.json was found 或 403 Forbidden。建议先手动 git clone 和 curl -I 验证每一步再交给 Composer。











