Composer 不支持子包拆分,subtree split 是 Git 层面操作,将主仓库子目录导出为独立仓库并打标签,供 Composer 消费;需配置 composer.json、autoload、tag 发布及 Packagist 同步。

Composer 本身不支持“子包拆分”这个操作——你不能靠 composer.json 配置把一个仓库自动切成多个包。所谓“subtree split”,是 Git 层面的手动或半自动同步,Composer 只负责消费已发布的包。
什么是 subtree split?它和 Composer 包发布是什么关系
Subtree split 是指从主仓库的某个子目录(比如 src/Http)单独导出历史,生成一个新的独立 Git 仓库,并打上版本标签。这个新仓库才能被 Composer 当作独立包安装(如 yourvendor/http-component)。Composer 从不读取你本地的目录结构,它只认 Packagist 或私有源上的合法包地址和版本。
- 主仓库保持完整开发流,所有功能、测试、CI 都在一个地方维护
- subtree split 后的新仓库只有该子目录的文件 + 精简后的提交历史(不含其他模块的变更)
- 你必须手动或用脚本把新仓库推送到远程(如 GitHub),再在 Packagist 上“add package”绑定
用 git subtree split 导出子目录时的关键参数
这是最常出错的环节:导出后发现历史缺失、文件为空、或无法 push 到新仓库。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 必须指定
--prefix,且路径末尾不加斜杠:git subtree split --prefix=src/Console -b console-split - 分支名(
-b)只是临时标记,导出后需git push <new-remote> console-split:main推到目标仓库的 main 分支 - 如果子目录曾被重命名或移动过,
--rejoin会干扰结果,**拆分子包时不要加--rejoin** - 第一次推送建议用
git push <new-remote> console-split:main --force-with-lease,避免因本地无对应分支导致失败
如何让 subtree 包支持 Composer 自动加载和版本管理
新仓库不是“放点代码就完事”。少了这几项,别人 composer require 会失败或无法自动引入类。
-
composer.json必须存在,"name"要唯一(如"yourvendor/console-component"),"autoload"指向该子目录内的实际 PSR-4 命名空间(如"YourVendor\Console\": "src/") - 每次发布新版本前,必须在新仓库里打 tag:
git tag v1.2.0,然后git push origin v1.2.0 - 如果你用私有 Packagist(如 Satis 或 Private Packagist),要确保它定时 reindex 这个新仓库;若用 Packagist.org,首次需手动 Submit Package 并验证 webhook
- 别把
vendor/、tests/或根级phpunit.xml放进 subtree —— 它们不属于组件运行时依赖
真正麻烦的不是命令怎么敲,而是每次主库提交后,你要判断哪些 subtree 需要重新 split、打 tag、触发 packagist 同步。自动化脚本容易漏掉 tag 推送或 autoload 路径更新,而手动操作又极易不同步。一旦主库和子包的版本号/类签名出现偏差,下游项目就会报 Class not found 或 Cannot declare class。这点在多人协作时尤其难追溯。

















