在 Gitee 中,要在一个代码仓库(主仓库)中嵌入多个其他仓库(子仓库),核心是利用 Git 原生的子模块(Submodule) 或 子树合并(Subtree Merge) 功能——这两种方法均兼容 Gitee(本质是 Git 仓库托管),且能实现“主仓库关联子仓库、保持同步更新”的需求,具体选择哪种取决于你的使用场景(是否需要子仓库独立维护、是否希望子仓库代码融入主仓库历史等)。
一、核心方法对比(先选对方案)
| 特性 | 子模块(Submodule) | 子树合并(Subtree Merge) |
|---|---|---|
| 本质 | 主仓库存储子仓库的“引用”(Commit ID + 地址) | 子仓库代码完全合并到主仓库,形成统一历史 |
| 子仓库独立性 | 强(子仓库仍是独立 Git 仓库) | 弱(子仓库代码融入主仓库,无独立引用) |
| 主仓库体积 | 小(仅存引用,子仓库代码需单独拉取) | 大(包含子仓库所有代码) |
| 同步子仓库更新 | 需手动更新子模块引用 | 可直接拉取子仓库分支合并到主仓库 |
| 提交影响 | 主仓库仅提交“子模块引用变更”,不影响子仓库 | 主仓库提交可能包含子仓库代码修改(需手动推子仓库) |
| 适用场景 | 子仓库独立维护、多项目复用(如公共组件库) | 希望子仓库代码融入主仓库、简化部署(如单仓库部署) |
推荐优先用「子模块」:大多数场景下(如主项目依赖多个独立维护的工具库、组件库),子模块更灵活,不会污染主仓库历史,且子仓库更新不影响主仓库稳定性。
二、方法一:子模块(Submodule)—— 推荐方案
核心逻辑
主仓库中创建一个“子目录”,该目录关联到目标子仓库,主仓库仅存储子仓库的 当前 Commit ID 和 仓库地址,子仓库代码需单独拉取/更新,且子仓库的提交完全独立。
操作步骤(全程命令行,Gitee 网页端仅需创建仓库)
1. 准备工作
- 已创建 主仓库(如
main-repo),并克隆到本地:bash git clone https://gitee.com/你的用户名/main-repo.git cd main-repo # 进入主仓库目录 - 需嵌入的 子仓库 已存在(如
sub-repo1、sub-repo2),获取其 Gitee 克隆地址(如https://gitee.com/你的用户名/sub-repo1.git)。
2. 添加子模块
在主仓库中执行 git submodule add,指定子仓库地址和本地存储路径(路径建议用子仓库名,如 submodules/sub-repo1):
# 格式:git submodule add 子仓库地址 本地存储路径
git submodule add https://gitee.com/你的用户名/sub-repo1.git submodules/sub-repo1
git submodule add https://gitee.com/你的用户名/sub-repo2.git submodules/sub-repo2
- 执行后,主仓库会生成两个关键文件:
.gitmodules:记录子模块的关联配置(仓库地址、本地路径),需提交到主仓库。- 子仓库路径(如
submodules/sub-repo1):作为“引用目录”,内部是子仓库的代码(但主仓库仅追踪其 Commit ID)。
3. 提交主仓库变更
添加子模块后,主仓库会有未提交的变更(.gitmodules 和子模块路径),需提交并推送到 Gitee:
git add .gitmodules submodules/sub-repo1 submodules/sub-repo2
git commit -m "添加子模块 sub-repo1 和 sub-repo2"
git push origin main # 推送到主仓库的主分支(如 main/master)
4. 查看 Gitee 效果
刷新主仓库的 Gitee 网页端,会看到 submodules/sub-repo1 目录显示为 蓝色链接,点击可直接跳转到子仓库——这是子模块的标志性特征,表明该目录关联了独立仓库。
5. 克隆包含子模块的主仓库(他人协作时)
如果他人克隆你的主仓库,默认不会自动拉取子模块的代码,需额外执行以下命令:
# 方法1:克隆主仓库时同时拉取子模块(推荐)
git clone --recursive https://gitee.com/你的用户名/main-repo.git
# 方法2:已克隆主仓库,后续拉取子模块
cd main-repo
git submodule init # 初始化子模块配置(读取 .gitmodules)
git submodule update # 拉取子模块的代码(基于主仓库记录的 Commit ID)
6. 同步子仓库的更新(子仓库有新提交时)
如果子仓库(如 sub-repo1)有新的代码提交,需在主仓库中更新子模块的引用:
# 进入子模块目录,拉取最新代码
cd submodules/sub-repo1
git pull origin main # 拉取子仓库的主分支最新代码
cd ../.. # 回到主仓库目录
# 主仓库会检测到子模块的 Commit ID 变更,提交该变更
git add submodules/sub-repo1
git commit -m "更新子模块 sub-repo1 到最新版本"
git push origin main
7. 删除子模块(如需移除)
# 1. 移除子模块引用
git submodule deinit -f submodules/sub-repo1
# 2. 删除子模块目录
rm -rf submodules/sub-repo1
# 3. 删除 .gitmodules 中的对应配置
git config -f .gitmodules --remove-section submodule.submodules/sub-repo1
# 4. 提交变更
git add .gitmodules
git commit -m "删除子模块 sub-repo1"
git push origin main
三、方法二:子树合并(Subtree Merge)—— 备选方案
核心逻辑
将子仓库的某个分支(如 main)完全合并到主仓库的一个目录下,子仓库代码会融入主仓库的提交历史,主仓库中看不到“子仓库引用”,仅显示普通目录和文件。适合需要将子仓库代码“打包”进主仓库、无需子仓库独立维护的场景。
操作步骤
1. 准备主仓库(同子模块步骤1)
克隆主仓库并进入目录:
git clone https://gitee.com/你的用户名/main-repo.git
cd main-repo
2. 添加子仓库为“远程仓库”
给主仓库添加子仓库的远程地址(命名为 sub-repo1,方便后续引用):
git remote add -f sub-repo1 https://gitee.com/你的用户名/sub-repo1.git
git remote add -f sub-repo2 https://gitee.com/你的用户名/sub-repo2.git
-f:添加远程时同时拉取子仓库的代码。
3. 合并子仓库到主仓库的指定目录
使用 git subtree add 将子仓库的分支合并到主仓库的目录(如 subtrees/sub-repo1):
# 格式:git subtree add --prefix=本地目录 远程仓库名 子仓库分支
git subtree add --prefix=subtrees/sub-repo1 sub-repo1 main --squash
git subtree add --prefix=subtrees/sub-repo2 sub-repo2 main --squash
--prefix=subtrees/sub-repo1:指定子仓库代码在主仓库中的存储目录。--squash:将子仓库的所有提交压缩为一个提交,避免主仓库历史过于冗长(可选,不加则保留子仓库完整历史)。
4. 提交并推送到 Gitee
git commit -m "合并子仓库 sub-repo1 和 sub-repo2 到 subtrees 目录"
git push origin main
5. 同步子仓库的更新(子仓库有新提交时)
# 1. 拉取子仓库的最新代码
git fetch sub-repo1 main
# 2. 合并到主仓库的子树目录
git subtree pull --prefix=subtrees/sub-repo1 sub-repo1 main --squash
# 3. 提交并推送
git commit -m "同步子仓库 sub-repo1 最新更新"
git push origin main
6. 从主仓库推送修改到子仓库(如需修改子仓库代码)
如果在主仓库中修改了子树目录(如 subtrees/sub-repo1)的代码,可推送到原教子仓库:
git subtree push --prefix=subtrees/sub-repo1 sub-repo1 main
四、关键注意事项
- 子模块的“引用一致性”:主仓库存储的是子模块的固定 Commit ID,他人协作时需确保拉取子模块的对应版本(否则可能出现代码不一致)。
- 子树的冲突处理:子树合并后,主仓库和子仓库的代码在同一目录下,若有文件同名可能出现冲突,需手动解决。
- Gitee 网页端操作限制:子模块和子树的添加/更新均需通过本地 Git 命令行操作,Gitee 网页端仅支持查看(子模块显示为链接,子树显示为普通目录)。
- 仓库权限:主仓库的协作者需同时拥有子仓库的读取权限(子模块)或写入权限(子树推送修改),否则无法拉取/推送子仓库代码。
总结
- 若子仓库需独立维护、多项目复用 → 选 子模块(Submodule)(Gitee 显示蓝色链接,灵活且不污染主仓库)。
- 若需将子仓库代码融入主仓库、简化部署 → 选 子树合并(Subtree)(Gitee 显示普通目录,代码一体化)。
两种方法均完全兼容 Gitee,核心操作依赖 Git 原生功能,无需 Gitee 额外配置,按步骤执行即可实现“一个主仓库嵌入多个子仓库”的需求。