## 一、子模块与主模块的关系

**结论：子模块的仓库和主模块的仓库不要求完全一致，它们是相互独立的 Git 仓库。**

|对比项|主模块（主项目）|子模块|
|---|---|---|
|Git 管理|必须是一个 Git 仓库|必须是一个合法的 Git 仓库|
|分支要求|任意分支|任意分支（主模块记录的是具体提交，不是分支名）|
|目录结构|任意|通常放在子目录，如 `src/` |
|权限要求|需要 push/pull 权限|需要 clone 权限|
|版本控制|只管理子模块的引用|管理实际代码|

关键点：

- 子模块是**独立的仓库**，有自己的分支、提交历史和 `.git` 目录。
    
- 主模块**只记录子模块的某个 commit hash**，不记录分支名，也不存储子模块的代码本身。
    
- 主模块的协作者必须能访问子模块的仓库，否则克隆后会失败。
    

---

## 二、子模块的常见问题

### 1. 子模块需要和主模块同分支吗？

**不需要。**

主模块只记录子模块的**固定提交**，例如 `abcdef123`，而不是分支名。

主模块的 `.gitmodules` 示例：

ini

[submodule "src"]
  path = src
  url = https://github.com/username/repo.git

主模块的 Git 记录的是子模块的 **commit hash**，不是分支。

---

### 2. 如何更新子模块？

主模块默认**不会自动更新**子模块的提交，需要手动操作：

bash

git submodule update --remote   # 拉取子模块的最新提交
git commit -m "Update submodule" # 提交主模块对子模块引用的更新

---

### 3. 克隆主模块时如何处理子模块？

克隆主模块后，子模块默认是**空目录**，需要初始化：

bash

git clone --recursive <主模块仓库地址>   # 一次性克隆主模块和子模块

或者：

bash

git submodule update --init --recursive  # 初始化已克隆主模块中的子模块

---

## 三、什么时候适合用子模块？

**✅ 适合场景：**

- 第三方依赖（如自定义修改的库）。
    
- 需要固定某个提交，避免依赖项自动更新导致冲突。
    

**❌ 不适合场景：**

- 频繁更新的代码（子模块需要手动同步）。
    
- 对 Git 不熟悉的团队协作（容易遗漏子模块操作）。
    

---

## 四、总结

1. **子模块和主模块的仓库是独立的**，不要求分支、结构或权限一致。
    
2. **主模块仅记录子模块的提交哈希**，协作时需确保子模块仓库可访问。
    
3. 使用 `git submodule update --remote` 更新子模块，并提交主模块的引用变更。
    
4. 如果需求更复杂（如动态分支跟踪），可以考虑 **Git Subtrees** 或依赖管理工具（如 pip/npm）。