subsplit 是将 git 仓库中子目录镜像为独立可 require 仓库的工具,解决单仓多模块复用问题;因 packagist 只识别完整仓库而非子路径,故需 subsplit 拆出并手动提交至 packagist。

subsplit 是什么,为什么不用 packagist 直接发布
subsplit 不是 Composer 官方工具,而是把 Git 仓库中某个子目录“切出来”当成独立仓库用的脚本。它解决的是「一个大项目里有多个可复用模块,但不想拆成 N 个独立 git 仓库来维护」的问题。比如 vendor/foo/laravel-package 实际只是你主仓库 my-org/app 下的 packages/laravel-package/ 目录。
直接 push 到 Packagist 行不通:Packagist 只认完整 Git 仓库,不识别子路径。subsplit 就是帮你把子目录“镜像”成一个真实存在的、可被 composer require 的独立仓库。
怎么初始化 subsplit 并推送第一个版本
先装工具:composer global require github:github/subsplit(注意不是 composer require 本地,是全局装)。然后进你的主仓库根目录,执行:
subsplit init https://github.com/my-org/app.git subsplit publish packages/laravel-package:refs/tags/v1.0.0 --no-tags
关键点:
-
packages/laravel-package必须是 Git 跟踪的路径,不能是软链或 .gitignore 排除项 -
--no-tags表示不自动同步所有 tag,避免误推开发分支的 tag;正式发版时才显式指定refs/tags/v1.0.0 - 目标仓库(如
my-org/laravel-package)必须提前在 GitHub 创建好,且你有写入权限 - 第一次运行会生成
.subsplit.yml,别删,后续 publish 都靠它映射路径
常见失败:push 被拒、tag 不同步、require 找不到包
最常卡在权限和配置上:
- 报错
remote: Permission to my-org/laravel-package.git denied→ 检查 SSH key 是否同时添加到主仓库和目标仓库的 GitHub 账户;用git@github.com:my-org/laravel-package.git格式而非 HTTPS - 运行
subsplit publish后 GitHub 上没新 commit → 确认.subsplit.yml里packages/laravel-package:后面没多余空格,且路径大小写与实际一致 -
composer require my-org/laravel-package提示Could not find package→ 目标仓库没在 Packagist 上手动 submit,subsplit 不自动注册;去 https://packagist.org/packages/submit 手动填https://github.com/my-org/laravel-package - 本地改了
packages/laravel-package/src/但 subsplit 没更新 → subsplit 只读取已git add && git commit的内容,未提交的修改完全不可见
发版流程中容易漏掉的一步
每次发新版,必须做三件事,缺一不可:
- 在主仓库里给子目录打 tag:
git tag -m "v1.0.1" v1.0.1 packages/laravel-package - 用 subsplit 推送到目标仓库:
subsplit publish packages/laravel-package:refs/tags/v1.0.1 - 去 Packagist 手动 trigger update(或配 webhook),否则
composer update还是拉不到新 tag
很多人以为 subsplit 推完就完了,结果发现 Packagist 页面上最新版还是半年前的——因为 Packagist 默认只在你首次 submit 或手动点击 “Update” 时抓取,不会监听 subsplit 的 push。










