聊聊 Git SubModule(子模块)

news2025/1/13 3:10:00

比如在公司不同开发团队中,有一个基础共享库,同时被多个项目调用。若要保证基础共享库的动态更新,那么就需要把共享库独立为一个代码库,但是分别把共享库中的文件拷贝到各自的项目中会造成冗余,而且再次更新共享库就会在不同项目下更新,会比较麻烦。

利用子模块可以作为解决该类问题的一种方案,子模块允许将一个Git仓库作为另一个Git仓库的子目录,并且可以独立地管理这个子仓库的版本,而且还能保持提交的独立性。

下面就通过实操来具体谈谈 Git submodule

一、什么是Git Submodule

Git Submodule 是Git版本控制系统中的一种机制,用于在一个Git仓库中包含另一个Git仓库。它允许将一个Git仓库作为另一个Git仓库的子目录,并且可以独立地管理这个子仓库的版本,同时还保持提交的独立。
image.png
Submodule的作用在于,它允许你在一个项目中使用其他项目的特定版本,而无需将整个子项目的代码复制到主项目中。这对于依赖管理和代码复用非常有用。

二、使用 Git Submodule

1 创建和初始化仓库

  • 初始化主库和子模块库

我采用的是 Gitee 来进行本次实操,首先在 Gitee 中创建一个主库 GitSubmoduleDemo,两个子模块库 ModuleAModuleB:
image.png
先将主库 clone 到本地:

$ git clone https://gitee.com/haohuin/git-submodule-demo.git
  • 在主库中,使用 git submodule add 命令添加 Submodule子模块。

其命令为:git submodule add <remote repo url> <local repo url>

  • remote repo url 指远程仓库的 url
  • local repo url 指本地仓库的路径 url
//在主库中添加ModuleA
$ git submodule add ../module-a.git ModuleA

//在主库中添加ModuleB
$ git submodule add ../module-b.git ModuleB

查看当前主库的状态:

$ git status
On branch master
Your branch is up to date with 'origin/master'.

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        new file:   .gitmodules
        new file:   ModuleA
        new file:   ModuleB

发现有新的文件在主库中,分别是 .gitmodules文件,ModuleAModuleB目录

1.1 .gitmodules文件

首先看一下 .gitmodules配置文件,它保存了远程仓库 url 与本地仓库 url 路径的映射:

[submodule "ModuleA"]
	path = ModuleA
	url = ../module-a.git
[submodule "ModuleB"]
	path = ModuleB
	url = ../module-b.git

每条记录对应一个子模块信息,path 和 url 对应远程仓库 url 和本地仓库路径

1.2 主库中的子模块

接着提交当前主库中出现的文件和目录:

//暂存
$ git add .
//提交
$ git commit -m "ModuleA and ModuleB submodule commit"
[master 2dcfefd] ModuleA and ModuleB submodule commit
 3 files changed, 8 insertions(+)
 create mode 100644 .gitmodules
 create mode 160000 ModuleA
 create mode 160000 ModuleB

发现ModuleAModuleB目录的模式编码为 160000
在之前讲解 index文件提到过,模式 160000是引用其他 Git 仓库的特殊文件类型,它允许将一个 Git 仓库作为另一个仓库的子目录进行管理。具体可以看这篇文章Git暂存区机制详解
所以此时主库中只是存储了子模块的引用,也就是一次的提交记录。而不是其他的文件或者目录。最后将主库中的修改进行推送:

$ git push origin master

image.png
发现在主库中ModuleAModuleB确实是以引用的形式存储的。

2 更新和同步子模块

那么如何将子模块的修改更新到主仓库中呢?这又分两种情况:

  • 在子模块所在的仓库中修改代码后提交,然后在主仓库中拉取更新
  • 在主仓库中修改子模块代码后提交远程仓库,然后在子模块仓库中拉取更新

2.1 主仓库更新子模块仓库中的修改

首先在子模块仓库 ModuleA 中新增一个文件,并提交到 ModuleA 的远程仓库中:

$ echo "updateModuleA-1">updateModuleA-1.txt
$ git add .
$ git commit -m "update ModuleA"
$ git push

image.png
此时子模块仓库中的 commit ID 值为 6026b48,再来看一下主仓库中的子模块的 Commit ID 值
image.png
发现此时主仓库的 Commit ID 值为 3474554,和子模块仓库中的 ID 值并不同步,所以需要在主仓库的子模块代码中同步子模块远程仓库的更新:

$ cd ModuleA
$ git checkout master
$ git pull origin master

然后在主仓库根目录中提交子模块仓库推送和更新:

$ cd ..
$ git add .
$ git commit -m "update ModuleA"
$ git push

此时发现远程主仓库已经同步子模块的更新内容,而且 Commit ID 值也同步成6026b48 ,和子模块仓库中最新的 Commit ID 保持一致:

image.png

2.2 子模块仓库更新主仓库中子模块代码的修改提交

首先在主仓库的子模块目录下修改代码:

//在主仓库中进入子模块ModuleA目录
$ cd ModuleA
//修改文件和提交和普通Git仓库提交流程一致:
//1.创建文件并提交
$ echo "ModuleA">updateModuleA.txt
$ git add .
$ git commit -m "update ModuleA"
//2.推送到远程ModuleA仓库
$ git push

发现远程子模块仓库也同步完成:

image.png

接着需要将主仓库中的子模块 ModuleA 的变化同步到远程主仓库中具体的操作和上一节主仓库更新子模块仓库中的修改类似,用 add 和 commit 方式提交主仓库的更新,这个时候就完成了子模块和主仓库代码一致。

$ cd ..
$ git add .
$ git commit -m "update ModuleA"
$ git push

在实际的 IDE 环境中,只需要在子模块目录下进行代码修改:

image.png
然后在提交时先更新子模块 ModuleB 的远程仓库:
image.png
然后再同步远程主仓库中的 ModuleB 目录变化,这一步需要用命令行,直接在主目录提交没法更新远程主目录,但是本地主仓库的 ModuleB 目录确实发生了变化:

$ git status
On branch master
Your branch is up to date with 'origin/master'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   ModuleB (new commits)

no changes added to commit (use "git add" and/or "git commit -a")

需要命令行切换到主仓库目录执行 git add 后再用 IDE 集成的 Git 提交操作:

$ git add .

再点击提交发现 IDE 中出现了 ModuleB 的更新变化:
image.png
接着推送到远程主仓库即可完成主仓库和子模块仓库的更新

三、总结

本文通过实践介绍子模块:

  • 包括子模块的初始化,如何使用 git submodule add 命令在主仓库添加子模块
  • 如何在子模块和主仓库之间的更新和同步

子模块主要有以下应用场景

  • 不同项目间需要共享同一个公共代码,如基础类库或工具包;
  • 较大的项目需要拆分成多个子项目进行开发,通过子模块控制依赖关系;
  • 第三方开源库或组件的本地开发与项目进行绑定;
  • 需要隔离成组和组件版本的同时利用依赖关系,如微服务架构下的服务与组件;
  • 子项目有较强的独立性同时也存在一定的耦合关系,通过子模块进行管理。

同时从上面的时间可以看到,子模块和主仓库之间的同步比较复杂,维护成本高,子模块与主项目需要进行紧密的协调管理,否则很容易导致不同步的情况出现。在使用中要结合实际情况下操作,简单的项目就不要用子模块,采用分支管理可能更合适。

参考资料

公共模块管理之 Git Submodule 使用总结
Git - 子模块
《Git 权威指南 蒋鑫著》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1459398.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

提升认知水平和防止偏见浅谈

提升认知水平和防止偏见浅谈 《庄子外物》&#xff1a;井蛙不可语海&#xff0c;夏虫不可语冰。 不要跟井底的青蛙谈论大海&#xff0c;因为它的认知只有井底那么大&#xff0c;大海对于它来说是认知盲区&#xff1b;不要与夏虫去谈论冰雪&#xff0c;因为夏虫一生很短没有经历…

香港优才计划认可大学名单有哪些?武大/西安交大/哈工大/中南大学毕业生,能加名校30分吗?

关注香港优才的朋友应该知道&#xff0c;优才计划采用计分制&#xff0c;综合计分制下&#xff0c;有一个“名校”加分项&#xff0c;如果毕业院校在世界百强大学名单内&#xff0c;可以多加30分&#xff01; 但这个世界百强大学名单&#xff0c;可能有很多人不是很清楚&#x…

用冒泡排序实现快速排序(qsort函数),指针进阶实例

目录 1、qsort函数是什么 2、冒泡排序实现指针进阶 2.1 主函数 2.2 功能函数声明​编辑 2.3 my_qsort函数介绍 2.4 Swap函数 总结 1、qsort函数是什么 qsort函数是c语言自带的函数&#xff0c;其功能是实现快速排序。我们来看一下他的参数和返回值&#xff1a; 以上就是q…

代码随想录算法训练营DAY21 | 二叉树 (9)

一、LeetCode 669 修建二叉搜索树 题目链接&#xff1a;669.修建二叉搜索树https://leetcode.cn/problems/trim-a-binary-search-tree/description/ 思路&#xff1a;递归三部曲-定参数、返回值-定终止条件-定单层递归逻辑 class Solution {public TreeNode trimBST(TreeNode …

深度学习基础——卷积神经网络(一)

卷积操作与自定义算子开发 卷积是卷积神经网络中的基本操作&#xff0c;对于图像的特征提取有着关键的作用&#xff0c;本文首先介绍卷积的基本原理与作用&#xff0c;然后通过编写程序实现卷积操作&#xff0c;并展示了均值、高斯与sobel等几种经典卷积核的卷积效果&#xff…

HTML-介绍-MDN文档学习笔记

HTML-介绍 查看更多学习笔记&#xff1a;GitHub&#xff1a;LoveEmiliaForever MDN中文官网 HTML-简介 MDN 文档引用&#xff1a; 就其核心而言&#xff0c;HTML 是一种相当简单的、由不同元素组成的标记语言&#xff0c;它可以被应用于文本片段&#xff0c;使文本在文档中具…

Security6.2 中的SpEL 表达式应用(权限注解使用)

最近学习若依框架&#xff0c;里面的权限注解涉及到了SpEL表达式 PreAuthorize("ss.hasPermi(system:user:list)")&#xff0c;若依项目中用的是自己写的方法进行权限处理&#xff0c; 也可以只用security 来实现权限逻辑代码&#xff0c;下面写如何用security 实现。…

[计算机网络]---UDP协议

前言 作者&#xff1a;小蜗牛向前冲 名言&#xff1a;我可以接受失败&#xff0c;但我不能接受放弃 如果觉的博主的文章还不错的话&#xff0c;还请点赞&#xff0c;收藏&#xff0c;关注&#x1f440;支持博主。如果发现有问题的地方欢迎❀大家在评论区指正 目录 一、端口号…

HarmonyOS - 实现多设备协同开发实战教程~

前言 现在随着个人设备越来越多&#xff0c;越来越需要多个设备之间相互感知和连接&#xff0c;设备和设备之间可以相互联动&#xff0c;形成互联互通的场景&#xff0c;而搭载HarmonyOS的设备恰好可以满足这一点 。下面通过开发一个HarmonyOS的多端分布式表白应用来实现设备之…

STM32_ESP8266 连接阿里云 操作图解

一、烧录MQTT固件 ESP8266出厂时&#xff0c;默认是&#xff1a;AT固件。连接阿里云需要&#xff1a;MQTT固件。 因此&#xff0c;我们需要给8266重新烧录 MQTT固件。 针对“魔女开发板&#xff0c;ESP8266模块烧录MQTT固件&#xff0c;图解教程如下&#xff1a; ESP8266 烧录 …

代码随想录算法训练营|二叉树总结

二叉树的定义&#xff1a; struct TreeNode {int val;TreeNode* left;TreeNode* right;TreeNode():val(0),left(nullptr),right(nullptr){}TreeNode(int val):val(val),left(nullptr),right(nullptr){}TreeNode(int val,TreeNode* left,TreeNode* right):val(val),left(left),…

网工内推 | 证券公司急招网工,base上海,年薪50W

01 广发证券 招聘岗位&#xff1a;网络工程师 任职要求&#xff1a; 1、懂基础建设网络&#xff0c;虚拟化&#xff0c;或者服务器中任意一个都可以&#xff08;需资深&#xff09;2、985/211本硕 3、年龄最好35以下 薪资待遇&#xff1a; 1、工作时间9:00-17:00 2、根据资历…

思腾合力邀您共赴第二届世界元宇宙大会

由中国仿真学会、中国指挥与控制学会和北京理工大学共同主办&#xff0c;上海市嘉定区安亭镇人民政府和中国仿真学会元宇宙专业委员会承办的第二届世界元宇宙大会大会以“虚实相生、产业赋能”为主题&#xff0c;聚焦元宇宙关键技术发展的共性问题&#xff0c;交流元宇宙技术产…

Window系统GPT-SoVITS配置安装

GPT-SoVITS配置安装 GPT-SoVITS配置Python下载以及安装源文件安装依赖 运行整理在安装配置环境时遇到的报错总结 GPT-SoVITS配置 作者链接 Python下载以及安装 版本这里根据教程的版本走即可&#xff0c;这里不会安装python或者不会配置环境的参考我之前的文章 Python 3.9,…

C# GTS四轴运动控制器实例(固高科技步进电机不带编码器)

注&#xff1a;由于电机不带编码器&#xff0c;无法做home和当前位置信息读取&#xff01; 功能&#xff1a; 三个轴的点位运动&#xff1a;前进后退&#xff0c;并分别显示每个轴的移动脉冲数(可以换算为距离)&#xff01; 开发环境&#xff1a;VS2017 硬件设备&#xff1a;固…

编程笔记 Golang基础 007 第一个程序:hello world 使用Goland

编程笔记 Golang基础 007 第一个程序&#xff1a;hello world 使用Goland 步骤1&#xff1a;启动GoLand并创建新项目步骤2&#xff1a;创建主包和主函数步骤3&#xff1a;运行程序小结 开始在Goland环境中编程go语言代码啦。 步骤1&#xff1a;启动GoLand并创建新项目 打开GoL…

[word] word中图片衬于文字下方无法显示 #媒体#微信

word中图片衬于文字下方无法显示 1、如图&#xff0c;图片“衬于文字下方”&#xff0c;文字下方的图象看不见 2、光标这位到图片上这段文字中&#xff0c;点击“格式”&#xff0d;“边框和底纹”&#xff0c;切换到“底纹”选项卡。可发现这两段文字底纹被设置成“白色”了 …

【数学建模入门】

数学建模入门 数学建模需要的学科知识怎么学习数学模型如何读好一篇优秀论文数学建模赛题常见类别数学建模常见问题数学建模组队和分工数学建模准备工作 数学建模需要的学科知识 怎么学习数学模型 &#x1f4a6;推荐阅读书籍&#xff1a; 《数学建模算法与应用》&#xff0c;…

OpenGL学习——17.模型

前情提要&#xff1a;本文代码源自Github上的学习文档“LearnOpenGL”&#xff0c;我仅在源码的基础上加上中文注释。本文章不以该学习文档做任何商业盈利活动&#xff0c;一切著作权归原作者所有&#xff0c;本文仅供学习交流&#xff0c;如有侵权&#xff0c;请联系我删除。L…

FlinkCDC详解

1、FlinkCDC是什么 1.1 CDC是什么 CDC是Chanage Data Capture&#xff08;数据变更捕获&#xff09;的简称。其核心原理就是监测并捕获数据库的变动&#xff08;例如增删改&#xff09;&#xff0c;将这些变更按照发生顺序捕获&#xff0c;将捕获到的数据&#xff0c;写入数据…