子模块中直接运行 composer install 会失败,因 git 子模块处于 detached head 状态,composer 拒绝向非分支检出点写入;需先 git checkout 主分支(或建临时分支),再执行安装。

子模块里直接跑 composer install 会失败?
因为 Git 子模块默认是“只读”状态,vendor/ 目录写入会被拒绝,尤其在 CI 或他人拉取后首次构建时。不是权限问题,是子模块的 Git 工作区处于分离头指针(detached HEAD)状态,Composer 默认拒绝向非分支检出点写入。
- 先用
git checkout main(或对应主分支名)切回分支,再运行composer install - 如果子模块没维护分支(比如只用 tag),就手动建一个:进入子模块目录 →
git checkout -b tmp-init→ 再装依赖 - CI 脚本里别省这步,否则
composer install静默跳过vendor或报错Could not write to /path/to/vendor
composer.json 在子模块里要不要加 repositories?
要,但只加真正需要覆盖的源——比如子模块依赖了你另一个私有包,而主项目已配过该源,子模块不声明,Composer 就找不到它。
- 子模块的
repositories是独立生效的,不会继承父项目的配置 - 避免重复定义 packagist.org;也别把主项目用的私有源全抄一遍,只补缺
- 若子模块依赖主项目的某个本地路径包(如
../my-lib),必须用path类型仓库,并确保路径相对于子模块根目录有效
主项目 composer update 会递归更新子模块吗?
不会。Composer 完全不感知 Git 子模块结构,composer update 只处理当前目录下的 composer.json 和 vendor/。
- 子模块的依赖更新必须手动进其目录执行
composer update或composer install - 想自动化?写个脚本遍历
.gitmodules,逐个cd进去操作,但注意:子模块可能未初始化(git submodule update --init得先跑) - CI 中常见坑:忘了在子模块目录下执行
composer install --no-dev,结果线上环境漏装生产依赖
如何让子模块的 autoload 被主项目识别?
靠主项目的 autoload-dev 或 autoload 手动映射,Composer 不自动扫描子模块。
- 在主项目
composer.json的autoload下加 PSR-4 映射,例如:"MySubModule\": "path/to/submodule/src/" - 路径必须是相对于主项目根目录的,不能写
./submodule/src/(.会被忽略) - 改完记得跑
composer dump-autoload,否则class not found - 如果子模块本身是可安装的包(有 name/version),更稳妥的做法是把它发布到私有仓库,主项目用
require声明,而不是硬连子模块路径










