聊聊 Git SubModule(子模块)

2024-02-19 17:28
文章标签 模块 聊聊 git submodule

本文主要是介绍聊聊 Git SubModule(子模块),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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

利用子模块可以作为解决该类问题的一种方案,子模块允许将一个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:   .gitmodulesnew file:   ModuleAnew file:   ModuleB

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

1.1 .gitmodules文件

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

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

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

1.2 主库中的子模块

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

//暂存
$ git add .
//提交
$ git commit -m "ModuleA and ModuleB submodule commit"
[master 2dcfefd] ModuleA and ModuleB submodule commit3 files changed, 8 insertions(+)create mode 100644 .gitmodulescreate mode 160000 ModuleAcreate 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 权威指南 蒋鑫著》

这篇关于聊聊 Git SubModule(子模块)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/725394

相关文章

python: 多模块(.py)中全局变量的导入

文章目录 global关键字可变类型和不可变类型数据的内存地址单模块(单个py文件)的全局变量示例总结 多模块(多个py文件)的全局变量from x import x导入全局变量示例 import x导入全局变量示例 总结 global关键字 global 的作用范围是模块(.py)级别: 当你在一个模块(文件)中使用 global 声明变量时,这个变量只在该模块的全局命名空

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于

git使用的说明总结

Git使用说明 下载安装(下载地址) macOS: Git - Downloading macOS Windows: Git - Downloading Windows Linux/Unix: Git (git-scm.com) 创建新仓库 本地创建新仓库:创建新文件夹,进入文件夹目录,执行指令 git init ,用以创建新的git 克隆仓库 执行指令用以创建一个本地仓库的

git ssh key相关

step1、进入.ssh文件夹   (windows下 下载git客户端)   cd ~/.ssh(windows mkdir ~/.ssh) step2、配置name和email git config --global user.name "你的名称"git config --global user.email "你的邮箱" step3、生成key ssh-keygen

查看提交历史 —— Git 学习笔记 11

查看提交历史 查看提交历史 不带任何选项的git log-p选项--stat 选项--pretty=oneline选项--pretty=format选项git log常用选项列表参考资料 在提交了若干更新,又或者克隆了某个项目之后,你也许想回顾下提交历史。 完成这个任务最简单而又有效的 工具是 git log 命令。 接下来的例子会用一个用于演示的 simplegit

记录每次更新到仓库 —— Git 学习笔记 10

记录每次更新到仓库 文章目录 文件的状态三个区域检查当前文件状态跟踪新文件取消跟踪(un-tracking)文件重新跟踪(re-tracking)文件暂存已修改文件忽略某些文件查看已暂存和未暂存的修改提交更新跳过暂存区删除文件移动文件参考资料 咱们接着很多天以前的 取得Git仓库 这篇文章继续说。 文件的状态 不管是通过哪种方法,现在我们已经有了一个仓库,并从这个仓

忽略某些文件 —— Git 学习笔记 05

忽略某些文件 忽略某些文件 通过.gitignore文件其他规则源如何选择规则源参考资料 对于某些文件,我们不希望把它们纳入 Git 的管理,也不希望它们总出现在未跟踪文件列表。通常它们都是些自动生成的文件,比如日志文件、编译过程中创建的临时文件等。 通过.gitignore文件 假设我们要忽略 lib.a 文件,那我们可以在 lib.a 所在目录下创建一个名为 .gi

取得 Git 仓库 —— Git 学习笔记 04

取得 Git 仓库 —— Git 学习笔记 04 我认为, Git 的学习分为两大块:一是工作区、索引、本地版本库之间的交互;二是本地版本库和远程版本库之间的交互。第一块是基础,第二块是难点。 下面,我们就围绕着第一部分内容来学习,先不考虑远程仓库,只考虑本地仓库。 怎样取得项目的 Git 仓库? 有两种取得 Git 项目仓库的方法。第一种是在本地创建一个新的仓库,第二种是把其他地方的某个

Git 的特点—— Git 学习笔记 02

文章目录 Git 简史Git 的特点直接记录快照,而非差异比较近乎所有操作都是本地执行保证完整性一般只添加数据 参考资料 Git 简史 众所周知,Linux 内核开源项目有着为数众多的参与者。这么多人在世界各地为 Linux 编写代码,那Linux 的代码是如何管理的呢?事实是在 2002 年以前,世界各地的开发者把源代码通过 diff 的方式发给 Linus,然后由 Linus

集中式版本控制与分布式版本控制——Git 学习笔记01

什么是版本控制 如果你用 Microsoft Word 写过东西,那你八成会有这样的经历: 想删除一段文字,又怕将来这段文字有用,怎么办呢?有一个办法,先把当前文件“另存为”一个文件,然后继续改,改到某个程度,再“另存为”一个文件。就这样改着、存着……最后你的 Word 文档变成了这样: 过了几天,你想找回被删除的文字,但是已经记不清保存在哪个文件了,只能挨个去找。真麻烦,眼睛都花了。看