把多个 github 仓库合并为单个仓库并保持双向同步——以我的计算机学习资料项目为例
1. 需求背景
已有 N 个独立课程仓库(JavaWeb、操作系统、计算机网络……)
想要再建一个「总仓库」SUST-Computer-Science-Study-Materials,统一对外展示。
要求:
- 保留各仓库完整历史
- 后续能在总仓库中直接修改文件,也能随时把改动同步回原仓库
- 尽量自动化,不增加日常负担
2. 解决方案
解决方案有两种,分别是 subtree 和 submodule。
方案对比(subsree vs submodule)
| 维度 | subtree(本文选用) | submodule |
|---|---|---|
| 历史保留 | 直接合并 | 需额外初始化 |
| 日常操作 | 正常 add / commit / push | 多一步 git submodule update |
| 冲突概率 | 低 | 高 |
| 双向同步 | 一条命令 | 极难 |
submodle主要是为了解决依赖管理问题,而不是合并仓库。 subtree更适合本文的需求。
3. 一次性初始化(subtree merge)
以下操作均在总仓库本地目录完成
3.1 克隆总仓库(本地已有总仓库则可忽略)
1
2
3
# 以前面提到的 总仓库 和 JavaWeb分仓库 为例
git clone https://github.com/marlin-phone/SUST-Computer-Science-Study-Materials
cd SUST-Computer-Science-Study-Materials
3.2 把课程仓库加为临时远程
1
git remote add javaweb https://github.com/marlin-phone/SUST-JavaWeb-Study-Materials
3.3 拉取并合并到子目录
1
2
git fetch javaweb
git subtree add --prefix=JavaWeb javaweb master --squash
参数说明:
--prefix=JavaWeb:指定把该仓库内容放到总仓库的哪个子目录下javaweb:上一步添加的远程仓库名master:远程仓库分支名(我的 JavaWeb 项目中使用的是 master,其它项目可能是 main)--squash:把所有历史压缩为一次提交(可选),不添加则会保留完整 git 历史
3.4 推回 github
1
git push
重复 3.2 - 3.4 步骤,则可把其他课程仓库也合并进来。
4. 日常手动双向同步(两条命令)
4.1 从分仓库拉取更新到总仓库
1
git subtree pull --prefix=JavaWeb javaweb master --squash
参数说明同上。
4.2 从总仓库推送更新回分仓库
1
git subtree push --prefix=JavaWeb javaweb master
注意
- 两条命令都在总仓库目录执行,小仓库无需任何操作。
- 出现冲突时按普通 merge 解决即可。
5. 自动化:GitHub Actions 双向同步
暂无该需求,待有需求后实现确认无误后补充。