Skip to content

子模块管理

EnderRealm 项目使用 Git 子模块来管理依赖的库和运行时环境。这个章节将教你如何管理子模块。

什么是子模块?

子模块(Submodule)是 Git 的一个功能,允许你将一个 Git 仓库作为另一个 Git 仓库的子目录。它常用于:

  • 管理依赖:将第三方库作为子模块引入
  • 共享代码:多个项目共享同一个库
  • 独立版本控制:子模块有自己独立的版本历史

为什么 EnderRealm 需要子模块?

EnderRealm 项目使用子模块来管理以下组件:

子模块路径用途
Easy4Formlibs/Easy4FormBedrock 玩家表单库
EnderRealmFastGUIlibs/EnderRealmFastGUI容器 UI 构建库
Floodgatelibs/FloodgateBedrock-Java 桥接(Fork)
EnderRealmRuntimeEnderRealmRuntime开发服务器运行时

子模块的工作原理

子模块本质上是一个指向特定提交的指针:

主仓库
├── .gitmodules          # 子模块配置
├── .git/modules/        # 子模块的实际 Git 仓库
├── libs/Easy4Form/      # 子模块的工作目录(指向特定提交)
└── ...

.gitmodules 文件

.gitmodules 文件定义了子模块的信息:

ini
[submodule "libs/Easy4Form"]
    path = libs/Easy4Form
    url = https://github.com/EnderRealmMC/Easy4Form.git

[submodule "libs/EnderRealmFastGUI"]
    path = libs/EnderRealmFastGUI
    url = https://github.com/EnderRealmMC/EnderRealmFastGUI

[submodule "libs/Floodgate"]
    path = libs/Floodgate
    url = https://github.com/EnderRealmMC/Floodgate.git

[submodule "EnderRealmRuntime"]
    path = EnderRealmRuntime
    url = https://github.com/EnderRealmMC/EnderRealmRuntime.git

子模块的日常操作

初始化子模块

如果克隆时没有使用 --recurse-submodules 参数,需要手动初始化:

bash
# 初始化并更新所有子模块
git submodule update --init --recursive

# 分步执行
git submodule init
git submodule update

更新子模块

bash
# 更新所有子模块到主仓库记录的版本
git submodule update

# 更新所有子模块到最新版本
git submodule update --remote

# 更新特定子模块到最新版本
git submodule update --remote libs/Easy4Form

查看子模块状态

bash
# 查看子模块状态
git submodule status

# 输出示例:
#  1a2b3c4d5e6f7g8h9i0j libs/Easy4Form (heads/main)
#  0j9i8h7g6f5e4d3c2b1a libs/EnderRealmFastGUI (heads/main)
#  9i8h7g6f5e4d3c2b1a0j libs/Floodgate (heads/main)
#  8h7g6f5e4d3c2b1a0j9i EnderRealmRuntime (heads/main)

前面的 - 号表示子模块未初始化,空格表示已初始化且与记录的版本一致,+ 表示子模块有新的提交。

进入子模块目录

bash
# 进入子模块目录
cd libs/Easy4Form

# 现在可以在子模块中执行 Git 命令
git log --oneline -5
git status

提交子模块更改

如果在子模块中做了修改:

bash
# 1. 进入子模块目录
cd libs/Easy4Form

# 2. 提交更改
git add .
git commit -m "修改了子模块"

# 3. 推送子模块更改
git push origin main

# 4. 返回主仓库
cd ../..

# 5. 更新主仓库中的子模块指针
git add libs/Easy4Form
git commit -m "更新 Easy4Form 子模块"

# 6. 推送主仓库更改
git push origin main

子模块的常见问题

Q: 子模块目录是空的?

A: 子模块未初始化,执行:

bash
git submodule update --init --recursive

Q: 子模块更新失败?

A: 尝试以下方法:

bash
# 方法 1:强制更新
git submodule update --force

# 方法 2:重新初始化
git submodule deinit -f libs/Easy4Form
git submodule update --init libs/Easy4Form

# 方法 3:删除并重新克隆
rm -rf libs/Easy4Form
git submodule update --init libs/Easy4Form

Q: 如何查看子模块的远程更新?

A: 使用以下命令:

bash
# 进入子模块目录
cd libs/Easy4Form

# 获取远程更新
git fetch

# 查看本地与远程的差异
git log HEAD..origin/main --oneline

# 返回主仓库
cd ../..

Q: 如何切换子模块的分支?

A: 使用以下命令:

bash
# 进入子模块目录
cd libs/Easy4Form

# 切换分支
git checkout feature-branch

# 返回主仓库
cd ../..

# 更新主仓库中的子模块指针
git add libs/Easy4Form
git commit -m "切换 Easy4Form 到 feature-branch"

Q: 子模块冲突怎么解决?

A: 当多人修改了子模块的指针时可能会产生冲突:

bash
# 1. 进入子模块目录
cd libs/Easy4Form

# 2. 切换到正确的版本
git checkout <正确的提交哈>

# 3. 返回主仓库
cd ../..

# 4. 解决冲突
git add libs/Easy4Form
git commit -m "解决子模块冲突"

子模块的最佳实践

1. 保持子模块同步

定期更新子模块,保持与上游同步:

bash
# 查看子模块是否有更新
git submodule foreach git fetch
git submodule foreach git log HEAD..origin/main --oneline

# 更新子模块
git submodule update --remote

2. 提交前检查子模块

在提交主仓库前,确保子模块处于正确状态:

bash
# 检查子模块状态
git submodule status

# 确保子模块没有未提交的更改
git submodule foreach git status

3. 使用 .gitmodules 管理配置

.gitmodules 文件应该被提交到仓库:

bash
git add .gitmodules
git commit -m "更新子模块配置"

4. 文档化子模块的使用

在 README 中说明子模块的用途和初始化方法。

子模块 vs 包管理器

Git 子模块和其他依赖管理方式的对比:

方式优点缺点
Git 子模块精确控制版本,可以修改源码操作复杂,容易出错
Maven/Gradle 依赖简单,自动管理无法修改源码
包管理器(npm/pip)简单,社区丰富可能与项目不兼容

EnderRealm 选择子模块的原因:

  • 需要修改 Floodgate 源码(Fork)
  • 需要精确控制库的版本
  • 库与项目紧密集成

常见问题

Q: 如何添加新的子模块?

A: 使用以下命令:

bash
# 添加子模块
git submodule add https://github.com/user/repo.git libs/repo

# 提交更改
git add .gitmodules libs/repo
git commit -m "添加新的子模块"

Q: 如何删除子模块?

A: 使用以下命令:

bash
# 1. 从 .gitmodules 中删除
git config -f .gitmodules --remove-section submodule.libs/repo

# 2. 从 .git/config 中删除
git config --remove-section submodule.libs/repo

# 3. 从暂存区删除
git rm --cached libs/repo

# 4. 删除本地文件
rm -rf libs/repo
rm -rf .git/modules/libs/repo

# 5. 提交更改
git add .
git commit -m "删除子模块"

Q: 如何克隆包含子模块的仓库?

A: 使用以下命令:

bash
# 方法 1:克隆时自动初始化子模块
git clone --recurse-submodules <url>

# 方法 2:克隆后手动初始化
git clone <url>
cd repo
git submodule update --init --recursive

推荐学习资源

下一步

子模块管理学习完成后,让我们进入阶段三:理解项目