【Git】Git Submodules 介绍(通俗易懂,总结了工作完全够用的 submodule 命令)

1、为什么你值得读这篇文章?

  • 一些技术博客写的很详细,但不适合新人学习。

  • 官方文档很全面,适合了解详细命令,但主次不分明。

本文会根据我的大量的 submodules 实践经验(包括工作和个人开发),只解释常用的命令。当你了解这些命令,你完全可以像我一样使用 Git Submodules。

2、为什么有 submodules?

  1. 解决公共代码问题。如果某些文件,在项目A和项目B中都会用到,例如组件库,那么这些文件可以作为 submodules 来管理,减少重复代码。(当然,该场景下npm包是另一解决方案,你需要选择一种方案。)

  2. 解决团队维护难题。如果一个大项目是一个大 Git 仓库,需要统一编译,不同的模块由不同团队维护,放在同一个 Git 仓库有诸多难处:例如多个团队的 MR 混在一起、权限难以区分等。这种情况即使公司内网 Git 权限做的足够精细,仓库管理员的学习成本也会很高,很难深度使用这种高级功能。为了解决多团队维护的难题,Git Submodules 也能大展身手,它可以让每个团队负责的模块就是一个 Git 仓库,这些 Git 仓库都被包含在同一个主 Git 项目下。(当然,微前端、微服务是另一种解决方案,你需要选择一种方案。)

3、了解 Git Submodules

有2个概念:主项目submodule(子模块)。这两者各自都是完整的 Git 仓库。

3.1、如何让一个Git仓库变为另一个Git仓库的 submodule

  1. 创建Git仓库A。
  2. 创建Git仓库B。
  3. 在Git仓库A中,通过git submodule add ...(仓库B的地址,即git clone时后面那串东西),可以把仓库B当作仓库A的submodule,此时A就成了主项目。【注:B也可以做A的主项目,通过在仓库B执行git submodule add ...(A地址)即可,因为二者都是完整Git仓库,在建立父子关系前,没有差异的。】

注意事项

  • 执行操作后,会在当前父项目下新建个文件夹,名字就是 submodule 仓库的名字。这个文件夹里面的内容,是 submodule 对应 Git 仓库的完整代码

  • 如果你希望换个名字,或者换个路径(例如放在某个更深的目录下),也是允许的,需要后面增加个路径参数,例如git submodule add ...(仓库地址) src/B(你希望 submodule 位于的文件夹路径)

3.2、submodule 的父子关系存在哪里

关系是保存在主项目的 Git 仓库中。

被当作 submodule 的 Git 仓库,其实不知道自己变成了 submodule,它更不知道爸爸们有谁。(意思是,当你打开某个被当作 submodule 的 Git 仓库首页时,或者拉下这个仓库时,没有任何痕迹表明它是个submodule。因为父子信息不存在这里,只存在爸爸那里。)

3.3、submodule 的父子关系信息怎么存

.gitmodules 文件

父子关系的信息保存在主项目的.gitmodules文件,如果不是新加 submodule,这个文件通常不必改变了,因为信息比较固定。

这个文件中主要记录了子模块的url,如果添加的时候使用的ssh链接,那这个url就是ssh,如果是https链接,这个url就是https

在这里插入图片描述

submodule 的版本号

主项目还保存了对应 submodule 的版本号(commit id),没有冗余存储 submodule 的代码。

可以看到,这其实是个跳转到另一个仓库的链接,指明了具体的 commit id。

这个版本号,是需要经常变更的。

在这里插入图片描述

4、submodule 开发常用操作

4.1、添加子模块

在github中创建了三个项目,其中git-learn为主项目,git-learn-submodules1和git-learn-submodules2为子项目
在这里插入图片描述

将git-learn克隆到本地,然后执行git submodule add ...(仓库B的地址,即git clone时后面那串东西)添加子模块到git-learn中

在这里插入图片描述
本地项目文件夹下面就多出来了两个文件夹(两个子项目)和一个文件(.gitmodules)

在这里插入图片描述
这是git上的目录,其中两个字模块用hash commit来维护,指向的是两个子仓库的地址

在这里插入图片描述

点击就跳转到对应子模块的目录:

在这里插入图片描述

到此,子模块初始化完成,接下来模拟实际工作场景

4.2、实际开发操作

4.2.1、将远端包含有子模块的代码克隆下来

git clone --recurse-submodules <主仓库url>

如:https://github.com/your-username/your-repository.git

在这里插入图片描述

4.2.2、建分支操作

下面以idea操作为例,使用idea打开git-learn文件夹

实际开发分为,develop、test、prod、master、feature、release和hotfix等,我们模拟简单建一下

在这里插入图片描述
从main新建一个prod分支,然后推送到远端,develop和test类似

建完后如下图:

在这里插入图片描述

4.2.2、子模块开发合并到develop/test

当我们要开发时,从最新的master新建一个feature分支,要注意的是,我们开发哪个模块,就只需要新建哪一个模块的feature就行,其他可以不用动

在这里插入图片描述
例如:我要开发git-learn-submodules1模块,从master新建一个feature/0716-xxxx分支

在这里插入图片描述
在这里插入图片描述
其中,git-learn-submodules1分支在feature/0716-xxxx分支,git-learngit-learn-submodules2在master分支

现在对git-learn-submodules1文件进行修改

在这里插入图片描述

提交修改,推送到远端开发分支

在这里插入图片描述
在这里插入图片描述

推送成功后,你的feature分支中就有了记录

在这里插入图片描述
现在,需要将你的代码,合到develop或者test分支,以develop为例

本地仓库切到develop分支,并且更新最新的develop代码(跟新最新代码,可以避免冲突):

在这里插入图片描述

merge最新的开发代码到develop环境中

在这里插入图片描述

成功以后develop会出现绿色小箭头,然后推送到远端仓库

在这里插入图片描述

在这里插入图片描述
这样你的开发环境中,就是最新的代码了,test同理

在这里插入图片描述

4.2.2、子模块和父模块开发合并到master

在这里插入图片描述

修改子模块和父模块

在这里插入图片描述

这个时候会出现下面情况

在这里插入图片描述
common-api.jsonsub1.txt是我们修改的文件是因为git-learn-submodules1子文件的hash不一致出现的问题(最新hash在develop,我们现在处与feature/0716-xxxx分支)

这种情况,我们先提交模块分支

在这里插入图片描述
然后推送到远端的feature/0716-xxxx分支

在这里插入图片描述
一般开发,没有合master权限,需要请求合并分支

在github (gitlab同理) 中子模块目录发起合并master请求

在这里插入图片描述

完成merge

在这里插入图片描述
这个时候,你的远端master上的git-learn-submodules1是最新的,需要拉到本地仓库,这个时候本地master就是最新的了

在这里插入图片描述
然后提交公共模块

在这里插入图片描述
然后按照同样的方法去发起merge请求操作。

到此,合并完成

5、总结

画了一个流程图,加深印象

在这里插入图片描述

通过官方文档,你可以了解到更多场景,但是我从来没使用过其它场景了,因为用不到。本文描述的完全满足了我所有日常使用场景。

而高级场景会导致协作变困难,因为不是所有开发者都懂这些更复杂的命令和配置

英文文档:https://www.git-scm.com/book/en/v2/Git-Tools-Submodules
中文文档:https://git-scm.com/book/zh/v2/Git-%E5%B7%A5%E5%85%B7-%E5%AD%90%E6%A8%A1%E5%9D%97

GitHub地址:https://github.com/huang-hanson/git-learn

在这里插入图片描述

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-17 05:56:02       66 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-17 05:56:02       70 阅读
  3. 在Django里面运行非项目文件

    2024-07-17 05:56:02       57 阅读
  4. Python语言-面向对象

    2024-07-17 05:56:02       68 阅读

热门阅读

  1. Go 语言中的互斥锁 Mutex

    2024-07-17 05:56:02       22 阅读
  2. k8s入门:从安装到实际应用

    2024-07-17 05:56:02       29 阅读
  3. ajax实时监测与springboot的实例分析

    2024-07-17 05:56:02       24 阅读
  4. 计算机网络入门 --网络模型

    2024-07-17 05:56:02       24 阅读
  5. 【Qt+opencv】计时函数与图像变换

    2024-07-17 05:56:02       26 阅读
  6. 简谈设计模式之适配器模式

    2024-07-17 05:56:02       24 阅读
  7. PR轨道蒙版|字体后放视频动画

    2024-07-17 05:56:02       24 阅读
  8. try-catch-finally使用注意事项

    2024-07-17 05:56:02       19 阅读
  9. IPython的数学魅力:%%latex命令绘制公式指南

    2024-07-17 05:56:02       24 阅读
  10. 采购管理软件:改善初创企业的采购流程

    2024-07-17 05:56:02       25 阅读
  11. 机体坐标系和导航坐标系

    2024-07-17 05:56:02       26 阅读
  12. 前后端工作重点小结

    2024-07-17 05:56:02       22 阅读