Composer 支持从本地 Git 仓库安装包,需满足:仓库含合法 composer.json(含 name、version 或 dev-* 分支名、type);require 中用 file:// 绝对路径 + repositories 配置 VCS 源;版本须为分支名(如 dev-main)或 tag(如 v1.0.0),不支持 ^ 约束。

Composer 可以直接从本地 Git 仓库安装包,无需推送到远程(如 GitHub),但必须满足 Git 仓库结构规范,且 composer.json 中的 type 和版本约束写法要匹配——否则会报 Could not find package xxx at version yyy 或静默失败。
本地 Git 仓库必须含有效 composer.json
Composer 不识别纯代码目录,只认 Git 仓库根目录下存在合法 composer.json 的项目。该文件需至少包含 name、version(或使用 dev-* 分支名作为版本)和 type(如 library)。
-
name必须全局唯一(如myorg/mylocal-package),不能与 Packagist 上已有包重名,否则 Composer 会优先拉远程 - 若不写
version,则必须通过分支名引用,例如dev-main或dev-develop;标签如v1.0.0也可被识别 - 本地路径不能用相对路径别名(如
../my-pkg),必须是绝对路径或 URL 形式(file:///full/path/to/repo)
在 require 中用 file:// 协议引用本地仓库
在项目根目录的 composer.json 的 require 段,直接写绝对路径 + file:// 协议,并指定开发分支或标签:
{
"require": {
"myorg/mylocal-package": "dev-main"
},
"repositories": [
{
"type": "vcs",
"url": "file:///Users/you/projects/mylocal-package"
}
]
}
-
repositories是必需的,告诉 Composer 这是一个 VCS 类型源,不是 Packagist -
url值必须是file://开头的绝对路径(Windows 下为file:///C:/path/to/repo) - 版本号必须对应 Git 分支名(
dev-main)或 tag 名(v2.1.0),不能写^2.1这类约束——本地 VCS 不支持稳定性过滤
常见错误:git 驱动未启用或权限拒绝
执行 composer install 时若报 Failed to clone ... failed to open stream: Permission denied,通常是 PHP 进程无权读取该路径,或 Git 未配置好 SSH/HTTPS 凭据(即使本地也走 Git 命令)。
- 确保
git --version可执行,且当前用户对仓库目录有读取权限(ls -l /path/to/repo检查) - 避免在
repositories.url中使用~/或环境变量,一律展开为完整绝对路径 - 如果仓库含子模块,需额外设置
"options": { "git": { "no-checkout": false } },否则可能跳过检出 - 调试时加
-vvv参数看 Composer 底层执行的git clone命令是否合理
替代方案:用 path repository(更轻量,无需 Git)
如果只是临时测试一个未初始化 Git 的代码目录,可用 path 类型仓库,它不依赖 Git,直接软链接或拷贝:
{
"require": {
"myorg/mylocal-package": "*"
},
"repositories": [
{
"type": "path",
"url": "/Users/you/projects/mylocal-package"
}
],
"minimum-stability": "dev",
"prefer-stable": false
}
-
path类型不要求 Git 初始化,也不校验composer.json的version -
"*"版本会自动映射到dev-master,且默认启用符号链接(composer install后在vendor/下是 symlink) - 注意:
path仓库无法发布到 Packagist,仅限本地开发;上线前必须切回 VCS 或 dist 方式
真正麻烦的不是配置,而是本地仓库的 composer.json 里漏写了 autoload 或 type,导致包能装上却无法自动加载——这点很容易被忽略,直到 Class not found 才回头检查。










