git submodule

news2024/11/16 8:17:51

文章目录

  • 环境
  • 准备
  • 用法
    • 添加子模块
      • 添加b
      • 添加c
      • 提交
      • 总结
    • 其它用户获取子模块
      • 其它
      • 总结
    • 更新子模块内容
      • 方式1:独立更新
        • 其它
      • 方式2:在主模块嵌套下更新
      • 总结
  • 总结
  • 参考

写的有点乱,凑合理解一下吧。另外常用命令总结一下:

  • git submodule add
  • git submodule init
  • git submodule update
  • git submodule foreach git pull
  • git clone xxx --recurse-submodules

环境

  • RHEL 9.4
  • git version 2.43.5

准备

在github里创建3个repository:

  • a :包含 a.txt
  • b :包含 b.txt
  • c :包含 c.txt

现在要把 a 作为主模块,并把 bc 作为其子模块,位于 a 的根目录下。

首先,新建目录 /root/test0822/test1 ,并克隆 a

[root@kai07221 test1]# git clone git@github.com:dukeding/a.git
Cloning into 'a'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
Receiving objects: 100% (3/3), done.

进入 a 目录下,查看文件结构:

[root@kai07221 a]# tree
.
└── a.txt

0 directories, 1 file

先看一下现在的 .git 目录(一会儿要做对比):

[root@kai07221 a]# ls -a
.  ..  a.txt  .git

[root@kai07221 a]# ls .git
branches  config  description  HEAD  hooks  index  info  logs  objects  packed-refs  refs

准备就绪。

用法

添加子模块

添加b

现在来添加子模块。使用 git submodule add 命令,添加 b

[root@kai07221 a]# git submodule add git@github.com:dukeding/b.git
Cloning into '/root/test0822/test1/a/b'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
Receiving objects: 100% (3/3), done.

此时,文件结构如下:

[root@kai07221 a]# tree
.
├── a.txt
└── b
    └── b.txt

1 directory, 2 files

可见,已经添加了子模块 b ,其内容都已经拉下来了。

不过,查看主模块此时的git状态:

[root@kai07221 a]# git status
On branch main
Your branch is up to date with 'origin/main'.

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

可见,对于主模块来说,子模块还没有提交。此外,还多了一个 .gitmodules 文件:

[root@kai07221 a]# ls -a
.  ..  a.txt  b  .git  .gitmodules

其内容如下:

[root@kai07221 a]# cat .gitmodules
[submodule "b"]
	path = b
	url = git@github.com:dukeding/b.git

.gitmodules 文件记录了子模块 b 的基本信息。

另外,作为对比,在 .git 目录下,多了一个 modules 目录:

[root@kai07221 a]# ls .git
branches  config  description  HEAD  hooks  index  info  logs  modules  objects  packed-refs  refs

其中包含了子模块的详细信息:

[root@kai07221 a]# ls .git/modules/
b

注: b 是一个目录,和一般的 .git 目录结构一样,包含了repo的详细信息。

进到子模块查看:

[root@kai07221 b]# git remote -v
origin	git@github.com:dukeding/b.git (fetch)
origin	git@github.com:dukeding/b.git (push)
[root@kai07221 b]# git status
On branch main
Your branch is up to date with 'origin/main'.

nothing to commit, working tree clean
[root@kai07221 b]# git branch
* main

和一般的repo一样,并没什么不同。

添加c

同理,再添加 c

[root@kai07221 a]# git submodule add git@github.com:dukeding/c.git
Cloning into '/root/test0822/test1/a/c'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
Receiving objects: 100% (3/3), done.

此时, .gitmodules 文件内容如下:

[root@kai07221 a]# cat .gitmodules
[submodule "b"]
	path = b
	url = git@github.com:dukeding/b.git
[submodule "c"]
	path = c
	url = git@github.com:dukeding/c.git

.git/modules 目录如下:

[root@kai07221 a]# ls .git/modules/
b  c

可见, .gitmodules 文件和 .git/modules 目录添加了 c 的信息。

提交

注意,对于主模块而言, bc 都还没提交:

[root@kai07221 a]# git status
On branch main
Your branch is up to date with 'origin/main'.

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

我们来提交一下,并push回去:

git commit -m "add b and c"
git push origin main

OK,至此,一切正常。

在github上:

在这里插入图片描述

注意: bc 指向的是commit号,不是某个branch。

总结

  • 通过 git submodule add 命令来添加子模块。
  • 子模块的状态和branch都是正常的。
  • .gitmodules 文件和 .git/modules/<子模块> 目录包含了子模块的信息。
  • .gitmodules 和子模块需要commit。
  • 在主模块里,子模块指向的是某个commit号。

其它用户获取子模块

新建目录 /root/test0822/test2 (模拟另外一个用户)。

首先克隆 a

git clone git@github.com:dukeding/a.git

进入 a 目录下,查看文件结构:

[root@kai07221 a]# tree
.
├── a.txt
├── b
└── c

2 directories, 1 file

可见,虽然有 bc 目录,但都是空目录。

此时有 .gitmodules 文件(这是test1用户提交的):

[root@kai07221 a]# ls -a
.  ..  a.txt  b  c  .git  .gitmodules
[root@kai07221 a]# cat .gitmodules
[submodule "b"]
	path = b
	url = git@github.com:dukeding/b.git
[submodule "c"]
	path = c
	url = git@github.com:dukeding/c.git

但并没有 .git/modules 目录。

要pull bc 的内容,需要运行 git submodule initgit submodule update 命令:

[root@kai07221 a]# git submodule init
Submodule 'b' (git@github.com:dukeding/b.git) registered for path 'b'
Submodule 'c' (git@github.com:dukeding/c.git) registered for path 'c'
[root@kai07221 a]# git submodule update
Cloning into '/root/test0822/test2/a/b'...
Cloning into '/root/test0822/test2/a/c'...
Submodule path 'b': checked out 'f11a1936c3b276885e50fefe96231025ef9881b6'
Submodule path 'c': checked out 'b504d5b012c468fb3d7363bd080b1b83d80823b8'

注意,commit号跟我们在github上看到的是一致的。

现在,bc 就有内容了:

[root@kai07221 a]# tree
.
├── a.txt
├── b
│   └── b.txt
└── c
    └── c.txt

2 directories, 3 files

看上去一切OK,但是要小心,此时进入 b ,查看状态:

[root@kai07221 b]# git status
HEAD detached at f11a193
nothing to commit, working tree clean

可见其状态是detached。查看其branch可见:

[root@kai07221 b]# git branch
* (HEAD detached at f11a193)
  main

也就是说,现在子模块并不在某一个branch上,而是在一个commit号上(参见github)。

切换到 main branch:

[root@kai07221 b]# git checkout main
Switched to branch 'main'
Your branch is up to date with 'origin/main'.

现在状态就OK了:

[root@kai07221 b]# git status
On branch main
Your branch is up to date with 'origin/main'.

nothing to commit, working tree clean

回到 a ,状态仍然OK(因为 b 切换branch时,并没有实际内容的修改):

[root@kai07221 a]# git status
On branch main
Your branch is up to date with 'origin/main'.

nothing to commit, working tree clean

c 也同理。

其它

那么有人可能会想,如果不在主模块里使用 git submodule update ,而是直接在子模块里pull,会怎么样?

经实测,这样做无效,也不报错,但是什么也pull不下来, b 目录下仍然是空的。

这是因为没有初始化子模块,所以即使在 b 目录下,仍然认为是在主模块里, b 目录只是一个普通的空目录:

[root@kai07221 b]# git remote -v
origin	git@github.com:dukeding/a.git (fetch)
origin	git@github.com:dukeding/a.git (push)

回到主模块( a 目录下),先 git submodule init 一下,然后再回来子模块, git remote -v 得到的仍然是a。只有 git submodule update 之后,得到的才是b。

总结

  • 克隆主模块时,不会获取子模块内容(子模块只是一个普通空目录,且仍然属于主模块)。
  • 需要 git submodule initgit submodule update 来获取子模块内容(获取的是指定的commit号,参见github)。
  • 子模块处于detached状态,要把它切换到某个branch(但是要小心,参见下面更新子模块)。

更新子模块内容

方式1:独立更新

子模块是独立的git repo,其更新跟一般git repo并无差异。

在github里,更新 b repo里面 b.txt 文件(和主模块无关,是独立更新),并提交。

在这里插入图片描述

  • 已存在用户(test1和test2):在主模块下, git pull origin maingit submodule update 都无法更新子模块。这是因为主模块无法感知到子模块的变化。
  • 新用户:也同理。新用户获取的子模块,其内容仍然是旧的。

其实这很容易理解。因为主模块里记录的子模块commit号没变(参见github)。

要想更新子模块内容,以test1用户为例,需要先到子模块里,pull一下:

[root@kai07221 b]# git pull origin main
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
Unpacking objects: 100% (3/3), 882 bytes | 882.00 KiB/s, done.
From github.com:dukeding/b
 * branch            main       -> FETCH_HEAD
   f11a193..61bfea2  main       -> origin/main
Updating f11a193..61bfea2
Fast-forward
 b.txt | 1 +
 1 file changed, 1 insertion(+)

然后回到主模块,可见其状态发生了变化:

[root@kai07221 a]# git status
On branch main
Your branch is up to date with 'origin/main'.

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:   b (new commits)

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

这是因为主模块记录的子模块信息和实际的子模块不一致了,换句话说,主模块感知到子模块发生了变化。

现在,就可以更新主模块了:

git add b
git commit -m "a update b"
git push origin main

这样,记录的子模块信息就更新了。github上的commit号如下:

在这里插入图片描述

现在,test2用户来获取更新。

在test2用户的主模块下做pull操作:

[root@kai07221 a]# git pull origin main
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 2 (delta 0), reused 2 (delta 0), pack-reused 0 (from 0)
Unpacking objects: 100% (2/2), 295 bytes | 295.00 KiB/s, done.
From github.com:dukeding/a
 * branch            main       -> FETCH_HEAD
   8d89f97..4102acd  main       -> origin/main
Fetching submodule b
From github.com:dukeding/b
   f11a193..61bfea2  main       -> origin/main
Updating 8d89f97..4102acd
Fast-forward
 b | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

但此时 b.txt 内容并不会更新。前面说过,对主模块的操作不会影响子模块。pull所得到的,是主模块所记录的子模块信息的更新。换句话说,对于test2用户,现在主模块所记录的子模块信息,和实际的子模块不一致了。

git submodule update 操作,令二者保持一致:

[root@kai07221 a]# git submodule update
Submodule path 'b': checked out '61bfea2af95a91c2e06f9d616675ab734107ac37'

可见, b 指向了commit号 61bfea2af95a91c2e06f9d616675ab734107ac37 (主模块所记录,参见github)

此时, b.txt 的内容就更新了。

和前面类似,此时进入到 b 目录,status变成detached:

[root@kai07221 b]# git status
HEAD detached at 61bfea2
nothing to commit, working tree clean

但这时一定要小心,如果切换到 main branch:

[root@kai07221 b]# git checkout main
Previous HEAD position was 61bfea2 Update b.txt
Switched to branch 'main'
Your branch is behind 'origin/main' by 1 commit, and can be fast-forwarded.
  (use "git pull" to update your local branch)

因为 main 是一个已存在的branch,且没有更新(仍然指向 f11a193... 那个commit号),切到该branch,会导致 b.txt 的内容变旧。(从上面输出结果也可以看到 Your branch is behind 'origin/main' by 1 commit 。)

而且主模块的status会不OK(因为记录的子模块信息和实际子模块内容不一致了)。此时如果在主模块下运行 git submodule update ,又会把子模块更新到 61bfea2... ……二者可以循环往复。

解决方法是,在子模块下运行 git pull 命令:

[root@kai07221 b]# git pull origin main
From github.com:dukeding/b
 * branch            main       -> FETCH_HEAD
Updating f11a193..61bfea2
Fast-forward
 b.txt | 1 +
 1 file changed, 1 insertion(+)

现在, b.txt 内容更新了,主模块和子模块的状态也都OK了。

其它

如果不运行 git submodule update ,而是分别在主模块和子模块做pull,是否可行呢?

经测试,这么做也OK。

所以,看起来 git submodule update 的作用,就是让子模块和“主模块所记录的子模块信息”保持一致。

当然,如果是一个新的用户test3,就不会有问题。其步骤为:

  1. 克隆主模块
  2. git submodule initgit submodule update 更新子模块
  3. 子模块的status不OK,到子模块下切换branch到main即可

方式2:在主模块嵌套下更新

在test1用户下,在 a/b 目录下更新 b.txt ,提交并push。

回到主模块 a ,查看状态:

[root@kai07221 a]# git status
On branch main
Your branch is up to date with 'origin/main'.

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:   b (new commits)

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

可见,至此,和方式1一样,后面的操作不再赘述。

总结

  • 在外部(远程)更新子模块,主模块不会感知。
  • 在内部(本地)更新子模块,主模块才会感知。
  • git submodule update 并不会更新某个branch,而是更新到了一个commit上,所以子模块会变成detached状态。如果要切回某个branch,注意代码是不是最新的(如果是本身已有的branch,考虑pull一下,确保获取最新内容)。

总结

  • 在主模块里使用 git submodule add 命令添加子模块
  • 在主模块里记录了子模块所指向的commit号
  • 更新子模块时内容,需要考虑同时更新主模块(更新其所记录的子模块信息)
  • 其它用户更新主模块时(比如pull操作),不会更新子模块内容,但会更新所记录的子模块信息(如果记录的信息有变化,将会导致二者不一致)
  • 使用 git submodule update 来更新子模块内容,其本质是按照所记录的子模块信息(commit号)来更新,更新后,子模块指向该commit号
  • 接上条,子模块指向某commit号,其状态是detached
  • 也可以直接在子模块里直接操作(比如pull)
  • 如果是新克隆的主模块,需要先运行 git submodule init 来初始化子模块,然后使用 git submodule update 来更新子模块内容

参考

  • https://blog.csdn.net/qq_38880380/article/details/123288706
  • https://blog.csdn.net/Java0258/article/details/108532507

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

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

相关文章

开发者空间实践指导:基于华为云3大PaaS主流服务轻松实现文字转换语音

案例简介 开发者将在云主机中&#xff0c;基于CodeArts API设计语音合成接口&#xff0c;基于API Explorer调试接口&#xff0c;并利用CodeArts IDE实现数据流转换为音频。在此过程中&#xff0c;开发者可体验API设计、开发、调试等全生命周期&#xff0c;对华为云产品API体系…

vue文件打包后怎么运行

找到打包后的文件 并在此处打开cmd控制台 输入 npm run serve 按住" ctrl " 再点击网址及可访问。 ------------------------------

代码行数计数器

做了个记录代码函数的小程序&#xff0c;后缀名记得设置为.pyw&#xff0c;如果你装了python的话可以直接拿来用&#xff0c;免费自取。 功能说明&#xff1a; 1.记录总行数、当前行数、目标行数三个值 2.具有进度条功能 3.行数的多少能激发不同的反馈&#xff0c;如great&am…

基于分数Talbot效应的阵列光学涡旋产生matlab模拟与仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 基于分数Talbot效应的阵列光学涡旋产生matlab模拟与仿真&#xff0c;分别测试正方形&#xff0c;旋转正方形以及六边形三种阵列形状下的光学涡旋。 2.测试软件版…

(论文研读)解决transform训练的不稳定性问题:SAMformer(时序预测)

论文链接&#xff1a;https://arxiv.org/abs/2402.10198 作者团队&#xff1a;华为诺亚方舟实验室&#xff08;华为巴黎研究中心&#xff09;&#xff0c;Laboratory of Informatics Paris Descartes (LIPADE) 巴黎笛卡尔大学&#xff08;第五大学&#xff09;信息学实验室 文…

【笔记篇】Davinci Configurator SomeIpXf模块

目录 1 简介1.1 架构概览2 功能描述2.1 特性2.2 初始化2.3 状态机2.4 主函数2.5 故障处理3 集成4 API描述5 配置1 简介 本文主要描述了AUTOSAR SomeIpXf模块的功能。 SomeIpXf主要用途是对数据进行SOME/IP格式的序列化和反序列化。 1.1 架构概览 SomeIpXf在AUTOSAR软件架构…

环绕音效是什么意思,电脑环绕音效怎么开

Boom 3D是一款专业的音效增强软件&#xff0c;它拥有先进的音效处理技术和丰富的音效设置选项&#xff0c;可以为用户打造出高度定制化的音频体验&#xff0c;Boom 3D还拥有简洁直观的界面&#xff0c;操作简单易懂&#xff0c;即使是音频技术的新手也能轻松上手。本篇文章就将…

Mybatis实现员工管理系统

文章目录 1.案例需求2.编程思路3.案例源码4.小结 1.案例需求 在上次做的父子模块的maven以及Ajax实现人工管理系统的基础上使用Mybatis实现员工管理系统的增删改查&#xff0c;具体运行效果如下&#xff1a; 2.编程思路 Mybatis框架的一般执行流程&#xff1a; 创建MyBati…

基于改进字典的大数据多维分析加速实践

一、背景 OLAP场景是大数据应用中非常重要的一环&#xff0c;能够快速、灵活地满足业务各种分析需求&#xff0c;提供复杂的分析操作和决策支持。B站主流湖仓使用Iceberg存储&#xff0c;通过建表优化可以实现常规千万级的指标统计秒级查询&#xff0c;这样就能快速搭建可视化报…

WRF输出结果的可视化展示与分析:以风速为例

1.前言 天气研究与预报 (WRF) 模型是一种功能强大的数值天气预报系统&#xff0c;用于模拟各种尺度的大气现象。WRF 生成大量输出数据&#xff0c;可为气象和气候研究、天气预报和环境管理提供宝贵信息。 WRF 输出数据通常存储在 netCDF 文件中&#xff0c;其中包含具有不同单位…

AI生成PPT怎么用?5款AI PPT工具助你轻松制作演示文稿

当你站在山西应县木塔之下&#xff0c;仰望这座千年古塔的雄伟与震撼&#xff0c;心中不禁涌起一股对历史与建筑艺术的敬畏之情。 想象一下&#xff0c;如果将这份震撼与敬仰融入到你的演示文稿中&#xff0c;那将是多么引人入胜的体验。而这一切&#xff0c;只需借助AI生成PP…

Kubernetes 运维工程师必备:K8s 基础面试题精编(三)

Kubernetes 运维工程师必备:K8s 基础面试题精编(三) 1. 在Kubernetes集群中如何查看Pod的日志?2. 如何将一个已经部署的应用程序从一个命名空间迁移到另一个命名空间?3. 如何更新Kubernetes集群中的应用程序镜像版本?4. 如何通过Kubernetes进行自动扩容?5. 如何手动扩容…

震惊!!大模型玩转JS逆向

不知道大家有没有被JS代码混淆折磨过&#xff0c;我之前搞爬虫的时候&#xff0c;也经常被OB代码混淆搞到心态崩溃&#xff0c;但是自从接触了大模型&#xff0c;腰不疼了&#xff0c;腿不酸了&#xff0c;OB代码直接交给大模型&#xff0c;简直不要太爽 这是一段经过OB混淆之…

盘点12个国内外主流CRM系统,哪一个能免费试用?

客户关系管理&#xff08;CRM&#xff09;系统已成为企业成功的关键工具。它们不仅帮助企业改善客户关系&#xff0c;还提高了销售效率和业务分析能力。在众多选择中&#xff0c;我们特意盘点了12个国内外主流的CRM系统&#xff0c;从地位、业务应用以及特点三方面进行解析&…

车牌号字符检测系统源码分享 # [一条龙教学YOLOV8标注好的数据集一键训练_70+全套改进创新点发刊_Web前端展示]

车牌号字符检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 研究背景与意义 随着智能交通系统的快速发展&#xff0c;车牌号字…

代码随想录算法训练营第 50 天 |98. 所有可达路径

代码随想录算法训练营 Day50 代码随想录算法训练营第 50 天 |98. 所有可达路径 目录 代码随想录算法训练营前言LeetCode98. 所有可达路径 一、图论基础概念1、图的种类2、度3、连通性&#xff1a;节点的连通情况4、图的构造5、图的遍历方式 二、深度优先搜索1、深度优先搜索的…

最全诗词近10万诗词大全ACCESS\EXCEL数据库

其实破解弄到这个数据库我没有多少喜悦&#xff0c;原因是我已有的一些诗词比如全唐诗、全宋词等加起来的话也差不多这个数&#xff0c;但是因为这个数据库是完整破解的&#xff0c;比自己用已有的诗词数据库整合来说更加的好&#xff1b; 分类情况统计&#xff1a;汉代诗词&am…

v500大程序之IIC调试

虽然写的是IIC&#xff0c;但其实在system bd中并没有勾选IIC0、IIC1&#xff0c;而是根据IIC协议写了相关的函数&#xff08;不是我写的&#xff09;。 用到的RTC是DS3231芯片。 目前遇到的问题是&#xff1a; zynq调试成功&#xff1b;fmql调试失败&#xff0c;其中年、日、…

【AD24报错】原理图编译后出现Off grid ## at的解决方案

【AD24报错】原理图编译后出现Off grid ## at的解决方案 在使用AD24进行原理图设计过程中&#xff0c;编译时出现Off grid ## at…错误。 1 错误原因 &#xff08;1&#xff09;元件放置不准确 在放置元件时&#xff0c;如果没有将元件的引脚或中心点准确地放置在网格点上&…

进程的创建、终止

目录 前言1. 进程创建2. 进程终止3. exit && _exit 的异同3.1 相同点3.2 不同点 前言 紧接着进程地址空间之后&#xff0c;我们这篇文章开始谈论进程控制相关的内容&#xff0c;其中包括进程是如何创建的&#xff0c;进程终止的几种情况&#xff0c;以及进程异常终止的…