对比维度代码大仓(Monorepo)普通仓库(Multirepo)
定义单个仓库中存储整个项目(或公司)的所有代码,包括多个应用、库、模块等。每个项目、应用或模块单独作为一个仓库,彼此独立存储。
代码边界代码共享通过内部引用(如相对路径),无物理隔离。代码共享通过包管理工具(如 npm、Maven),有物理隔离。
版本管理整个仓库使用统一版本号(或无版本号),一次提交影响全局。每个仓库独立版本号,变更仅影响单个仓库。
权限控制通常对仓库整体授权,细粒度控制较复杂。可针对单个仓库精确控制权限,安全性隔离性更强。
典型工具Git(配合 Git Subtree)、Google Repo、Perforce 等。Git(默认多仓库模式)、SVN 等。

代码大仓(Monorepo)

优点:

  • 代码共享便捷:不同模块 / 应用可直接引用内部代码,无需发布成外部包,减少 “重复造轮子”。
  • 原子化变更:跨模块的修改可在一次提交中完成,避免多仓库同步更新的繁琐(如 A 依赖 B,修改 B 后需先发布再更新 A)。
  • 统一规范与工具:容易维护统一的编码规范、构建工具和 CI/CD 流程,降低配置碎片化。
  • 简化依赖管理:避免依赖版本冲突,所有代码使用同一套依赖环境(如同一版本的 Node.js、Python)。
  • 便于代码重构:跨模块重构时,可一次性修改所有相关代码并验证,减少遗漏。

缺点:

  • 仓库体积庞大:随着项目增长,仓库体积可能达到 GB 级,拉取、克隆速度慢,占用本地存储空间大。
  • 权限控制复杂:难以精确限制团队只能修改特定模块,可能存在误操作风险(如新手修改核心代码)。
  • 构建效率问题:全量构建耗时极长,需依赖高级工具(如 Bazel、Nx)实现增量构建,学习成本高。
  • 历史记录混乱:所有修改混在一个仓库的提交记录中,定位特定模块的历史变更较困难。
  • 团队协作成本高:多人同时修改时,冲突概率增加,需要更严格的分支管理策略。

适用场景:

适合中小型团队、业务关联紧密的项目(如前端单页应用 + 组件库 + 工具库)、需要频繁跨模块协作的场景(如 Google、Facebook 内部项目)。

Git Subtree 

Git Subtree 是 Git 中用于管理代码仓库间依赖关系的一种技术,允许将一个仓库(子仓库)作为另一个仓库(主仓库)的子目录嵌入,同时保持子仓库的独立性。它是解决代码复用问题的方案之一,尤其适合在不采用 Monorepo 整体架构的情况下,实现部分代码的共享管理。

 引入子仓库(首次添加)

git subtree add --prefix=路径/子目录名 子仓库URL 分支名 --squash
  • --prefix:指定子仓库在主仓库中的存储路径
  • --squash:将子仓库的历史压缩为一个提交,避免主仓库历史过于臃肿
git subtree add --prefix=libs/utils https://github.com/example/utils-repo main --squash

从子仓库拉取更新

git subtree pull --prefix=路径/子目录名 子仓库URL 分支名 --squash

实际开发中,部分团队会采用 “混合策略”(如核心库用大仓管理,业务应用用多仓库),平衡两种模式的优势。