path仓库不支持git子模块,必须先解除嵌套关系:子模块需手动初始化、提交并确保composer.json中name与require逐字一致,url用"./modules/foo"等相对路径,且须启用"options":{"symlink":true},否则composer静默跳过。

path仓库不支持git子模块,必须先解除嵌套关系
Composer 的 type: "path" 仓库根本不识别 git 子模块(submodule)——它只认一个独立目录下有合法 composer.json 的普通文件夹。如果你把包作为子模块拉进 modules/foo,但没手动初始化或提交过,Composer 就会静默跳过,连 warning 都不抛。
常见错误现象:composer install 报 Could not find package vendor/name,而 ls modules/foo/composer.json 确实存在;git submodule status 显示子模块已检出,但 composer config repositories 输出里压根没你配的条目。
- 子模块目录默认是空的(只有 .git 文件),除非你运行过
git submodule update --init,否则里面根本没有composer.json - 即使子模块已更新,它的
composer.json也必须满足:有name字段、且与主项目require中的字符串逐字一致(大小写、斜杠方向都不能错) - 子模块路径在
repositories.url中必须写成相对路径,如"./modules/foo",不能写"modules/foo"(缺./前缀)或"../modules/foo"(路径错位)
怎么让子模块真正被 path 仓库识别
不是“配置完就生效”,而是要确保子模块目录具备独立包的所有特征:有完整 Git 历史、有 composer.json、能被 symlink —— 缺一不可。
- 进入子模块目录,执行
git init(如果还没初始化)、git add .、git commit -m "init";仅靠git submodule add不够,它不自动 commit 子模块内容 - 确认子模块根目录下
composer.json的name和主项目require完全一致,例如都为"acme/utils",不能是"Acme/Utils"或"acme-utils" - 主项目
composer.json的repositories必须写在顶层,格式为:{ "type": "path", "url": "./modules/foo", "options": {"symlink": true} } - 运行
composer update acme/utils(不是install),因为已有 vendor 条目时install不刷新 symlink
验证 symlink 是否真建成了
别信命令输出里的 “Installing” 字样,得看文件系统本身。Composer 在失败时倾向 fallback 到 copy 模式,而你根本不会收到提示。
- Linux/macOS 下运行:
ls -la vendor/acme/utils,输出中必须含-> ./modules/foo才算成功;如果只是普通目录,说明 symlink 创建失败 - Windows 下用管理员权限打开终端,运行:
dir vendor\acme\utils,看到<symlinkd></symlinkd>或JUNCTION才对 - 若失败,检查点:子模块目录是否可写、当前用户是否有权限创建符号链接、主项目
config是否设了"symlinks": false
为什么不用 vcs 类型直接引用子模块仓库
因为 type: "vcs" 和 type: "path" 是两条完全不同的链路:前者走 Git 协议克隆远程仓库,后者走本地文件系统直连。子模块本质是“已挂载的远程仓库副本”,Composer 不会把它当成本地路径处理。
-
vcs类型要求url是完整 Git 地址(如git@github.com:org/pkg.git),不能是./modules/foo - 子模块的远程地址和本地路径是解耦的;你在
repositories里配子模块的远程 URL,Composer 会重新 clone 一份,而不是复用已有的子模块内容 - 想复用子模块代码,唯一可靠路径就是把它当成普通本地目录对待:先确保它内容完整、可读、有 composer.json,再用
path引入











