当前位置: 首页 > news >正文

Git 子模块 (Submodule) 完全使用指南

Git 子模块 (Submodule) 完全使用指南

核心原理解析:子模块是什么?

想象一下,你在开发一个大项目(父项目),需要用到另一个独立的项目(例如一个公共库、一个UI组件库)。你不想直接复制粘贴它的代码,因为那样就无法方便地获取那个库的后续更新。

Git 子模块就是来解决这个问题的。它允许你将一个 Git 仓库作为另一个 Git 仓库的子目录。

最重要的核心原理:

父项目不存储子模块的所有文件内容。它只存储一个**“指针”,这个指针精确地指向子模块仓库的某一个特定的 Commit ID**。

这就是理解所有子模块操作的关键。当你更新、切换父项目的分支时,这个“指针”会跟着改变,指向子模块在那个时间点应该使用的版本。


第一部分:添加一个新的子模块

场景:

你的主项目 MyProject 需要引入一个外部库 SharedLibrary

💻 命令行操作
  1. 添加子模块
    在你的父项目 MyProject 的根目录下,执行以下命令:

    # git submodule add <仓库URL> <存放路径>
    git submodule add https://github.com/user/SharedLibrary.git libs/shared-library
    

    这个命令做了三件事:

    • 克隆 SharedLibrary 仓库到 libs/shared-library 目录。
    • 创建一个 .gitmodules 文件(如果它不存在的话),用来记录子模块的信息。
    • 将子模块的当前最新 Commit 添加到父项目的暂存区。
  2. 提交父项目的变更
    运行 git status,你会看到:

    new file:   .gitmodules
    new file:   libs/shared-library
    

    现在,提交这个变更来正式将子模块“注册”到你的父项目中:

    git commit -m "feat: Add SharedLibrary as a submodule"
    git push
    
🐢 TortoiseGit 操作
  1. 在父项目 MyProject 的根目录空白处右键,选择 TortoiseGit -> Submodule Add… (添加子模块)。
  2. 在弹出的对话框中:
    • Repository: 填入子模块的仓库 URL (例如 https://github.com/user/SharedLibrary.git)。
    • Path: 填入你想存放子模块的本地路径 (例如 libs/shared-library)。
    • Branch: 可以留空,默认会使用远程仓库的默认分支。
  3. 点击 OK。TortoiseGit 会自动执行添加操作。
  4. 操作完成后,你会发现父项目有文件变更。右键父项目 -> Git Commit…
  5. 在提交窗口,你会看到新增的 .gitmodules 文件和 libs/shared-library 文件夹。填写提交信息,然后 Commit & Push

第二部分:克隆与更新含有子模块的项目

场景:

你的同事需要克隆 MyProject,或者你需要拉取包含了子模块更新的父项目。

💻 命令行操作
  1. 首次克隆项目
    使用 --recurse-submodules 参数,可以在克隆父项目时自动初始化并拉取所有子模块。

    git clone --recurse-submodules <父项目的URL>
    

    如果你忘记加参数,也可以分步操作:

    git clone <父项目的URL>
    cd MyProject
    git submodule update --init --recursive
    
    • --init: 初始化本地的 .git/config 文件,注册子模块信息。
    • --recursive: 如果子模块还包含了其他子模块,也一并处理。
  2. 拉取父项目的更新 (可能包含子模块指针的变更)
    日常工作中,你拉取了父项目的更新,发现它指向了子模块的一个新版本。

    # 1. 拉取父项目的变更
    git pull# 2. 根据父项目最新的指针,更新子模块的代码
    git submodule update --recursive
    
🐢 TortoiseGit 操作
  1. 首次克隆项目

    • 右键 -> Git Clone…
    • 在克隆对话框中,填入 URL 和目录后,勾选 “Recursively clone submodules” (递归克隆子模块)。
  2. 拉取父项目的更新

    • 右键父项目 -> Git Sync… -> 点击 Pull 拉取父项目更新。
    • 拉取后,右键父项目 -> TortoiseGit -> Submodule Update… (更新子模块)。
    • 在对话框中,确保 “Initialize submodules” (初始化子模块) 被勾选,然后点击 OK

第三部分:修改、提交和推送子模块

由于子模块默认处于“分离头指针”(Detached HEAD)状态,我们必须先子模块切换到分支(主分支 or 你指定的分支)后,才能进行修改

注:在“分离头指针”这种状态下,你依然可以提交代码,但这些提交不属于任何分支。当你试图用 git push origin HEAD 推送时,Git 懵了:

  • 你 (Source): “把 HEAD 指向的这个 commit 推上去!”
  • Git (Destination): “推到远程仓库 (origin) 的哪里去呢?HEAD 在远程不是一个合法的分支名。我不知道该在远程创建/更新哪个分支。”
场景:

你需要修复 SharedLibrary 子模块里的一个 Bug。

💻 命令行操作
  1. 进入子模块并切换到分支

    # 1. 进入子模块目录
    cd libs/shared-library# 2. 检查状态,你会看到 "HEAD detached at..."
    git status# 3. 切换到你想修改的分支(例如 main)
    git checkout main# 4. (强烈推荐) 拉取最新代码,确保你的修改基于最新版本
    git pull
    
  2. 修改、提交并推送子模块
    现在你可以像操作任何普通 Git 仓库一样操作它。

    # ... 在这里修改文件 ...
    git add .
    git commit -m "fix: 修复了 SharedLibrary 中的某个重要 Bug"
    git push origin main
    

    至此,子模块本身的代码已经推送到它自己的远程仓库了。但父项目还不知道这个变化。

  3. 更新父项目的指针

    # 1. 回到父项目根目录
    cd ../..# 2. 检查状态,你会看到子模块被标记为 "modified (new commits)"
    git status
    # 输出会像这样:
    #   modified:   libs/shared-library (new commits)# 3. 添加这个变更到暂存区
    git add libs/shared-library# 4. 提交并推送父项目的更新
    git commit -m "chore: 更新 SharedLibrary 子模块以修复 Bug"
    git push
    
🐢 TortoiseGit 操作
  1. 进入子模块并切换到分支

    • 在文件浏览器中,右键子模块文件夹 (libs/shared-library)。
    • 选择 TortoiseGit -> Switch/Checkout…
    • 在对话框中,选择 “Branch”,然后从下拉菜单中选择 main 分支,点击 OK
    • (推荐) 再次右键子模块文件夹 -> Git Sync… -> Pull
  2. 修改、提交并推送子模块

    • 在子模块文件夹内修改代码。
    • 右键子模块文件夹 -> Git Commit -> ‘main’…
    • 填写提交信息,勾选文件,点击 Commit
    • 在弹出的成功对话框中,点击 Push。确认推送信息后,点击 OK
  3. 更新父项目的指针

    • 回到父项目根目录
    • 右键父项目文件夹空白处 -> Git Commit…
    • 在提交窗口,你会看到 libs/shared-library 被列为“已修改”。
    • 勾选它,填写提交信息(例如:“chore: 更新子模块”),然后点击 Commit
    • 在成功对话框中,点击 Push,将父项目的更新推送到远程。

总结与最佳实践

  1. 核心牢记: 父项目只记录子模块的一个 Commit ID
  2. 双重提交: 修改子模块永远是两步操作:先在子模块内部 commit & push,再回到父项目 commit & push 更新指针。
  3. 进入再改: 修改子模块前,永远先 cd 进去,然后 git checkout 到一个分支。
  4. 及时更新: 拉取父项目更新后,记得运行 git submodule update 来同步子模块代码。
  5. 沟通: 如果团队协作,当你更新了子模块指针并推送到父项目后,一定要通知其他成员,让他们知道需要运行 git submodule update

希望这篇详尽的教程能帮你彻底掌握 Git 子模块的使用!

相关文章:

  • 最少收藏十个域名网站百度关键词优化培训
  • 无锡宏腾网站建设国家免费培训学校
  • 吉林省城乡建设部网站百度搜索引擎优化怎么做
  • 网站多语言建设seo关键词排名优化系统源码
  • 给小孩子做网站网络推广公司经营范围
  • 开发手机网站用什么语言搜索引擎排名中国
  • 【Vue】 keep-alive缓存组件实战指南
  • AI智能化高效办公:WPS AI全场景深度应用指南
  • MySQL之SQL性能优化策略
  • LayUI的table实现行上传图片+mvc
  • PyTorch topk() 用法详解:取最大值
  • CI/CD GitHub Actions配置流程
  • mongoose解析http字段值
  • 【LLaMA-Factory 实战系列】三、命令行篇 - YAML 配置与高效微调 Qwen2.5-VL
  • 走近科学IT版:FreeBSD系统下ThinkPad键盘突然按不出b和n键了!
  • Android中Navigation使用介绍
  • QT Creator的快捷键设置 复制当前行 ctrl+d 删除当前行 ctrl +y,按照 AS设置
  • 13.5-13.8. 计算机视觉【2】
  • jar 包如何下载
  • 网页变形记:响应式设计如何在手机里 “七十二变”
  • 【unitrix】 4.3 左移运算(<<)的实现(shl.rs)
  • 医疗AI数智立体化体系V2.0泛化多模块编程操作手册--架构师版(下)
  • Docker Compose与私有仓库部署
  • 多项目资料如何统一归档与权限管理
  • 2023/7 N2 jlpt词汇
  • uniapp实现远程图片下载到手机相册功能