Git 子模块submodule 小记

子模块(submodule)是一个内嵌在其他 git 仓库(主项目)中的 git 仓库。

  • submodule是一个独立git 仓库,(几乎)不受主项目的影响;主项目来管理具体如何使用子项目
  • 主项目总是指向每个submodule的一次commit,因为提交后的commit不会受后续 submodule开发的影响,这样可以保证主项目的依赖不会发生变化,不会受到子项目后续开发的影响
  • git 是目录相关的,在主项目目录下就是操作主项目,当cd到子项目的目录后,命令都是操作对应的 submodule

查看submodule状态

因为 submodule 本身是独立的,那么不管是你自己或者 submodule 的维护者更新后,都需要主项目管理者来决定是否需要更新 submodule :

  • submodule 的远程仓库有更新
  • submodule 的本地有更新

当我们 clone 了一个项目,并使用git submodule status查看 submodule 的状态:

 34777f2e91b72cdc62a415975cc3ec53475ed022 3rdparty/QHotkey (1.5.0-6-g34777f2)
 050293646fc0337cfdb5084bf16f3d6efc84e9d8 3rdparty/fmt (9.1.0-205-g05029364)
 a738fdf9338412f83ab3f26f31ac11ed3f3ec4bd 3rdparty/gflags (v2.2.2-47-ga738fdf)
 674283420118bb919f83ceb3d9dee31ef43ff3aa 3rdparty/glog (v0.4.0-328-g6742834)

其中,每个 submodule 状态行最后括号中的 g05029364包含的数字代表该 submodule 本地HEAD指向的commit, 如果希望拉取子项目的远程更新,则执行

git submodule update --remote

此时,submodule 的远程更新被拉取到本地,并检出变成了本地更新

Submodule path '3rdparty/fmt': checked out 'cbc7b8d5c1a0a88671fa1497d9e09197fde334f2'

此时在主项目中查看 submodule 的状态

 34777f2e91b72cdc62a415975cc3ec53475ed022 3rdparty/QHotkey (1.5.0-6-g34777f2)
+cbc7b8d5c1a0a88671fa1497d9e09197fde334f2 3rdparty/fmt (9.1.0-206-gcbc7b8d5)
 a738fdf9338412f83ab3f26f31ac11ed3f3ec4bd 3rdparty/gflags (v2.2.2-47-ga738fdf)
 674283420118bb919f83ceb3d9dee31ef43ff3aa 3rdparty/glog (v0.4.0-328-g6742834)

这里例子里,只有fmt一个仓库有更新

可以看到 hash 值前面多了一个+(也可以看到其HEAD指向的commit改变了),这表明主项目依赖的 submodulecommit 和此时 submoduleHEAD 不一致了,进入子项目cd 3rdparty/fmt 并查看其状态git status:

HEAD detached at cbc7b8d5
nothing to commit, working tree clean

回到主项目目录,查看主项目的状态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:   3rdparty/fmt (new commits)

此时,可以看到主项目检测到了子项目的更新,并作为主项目本身的修改,如果此时在主项目中提交了更新,主项目就会指向这个 submodule 的最新的 commit

如果此时,你想要保持主项目对 submodule 的依赖不变,那么你只要

git submodule update

还比如主项目远程仓库更新了依赖,而你仅仅拉取了主项目的更新,此时你本地的主项目依赖和子模块是不一致的

这样,本地的 submodule 将状态更新为主项目依赖的 commit 状态。

注意,git submodule update更新时,会使得子模块处于 detached HEAD 状态,也就是更新会被覆盖掉。因此在子模块修改时,一定要 checkout 一个分支。

常用指令

添加子模块

git submodule add <Git 仓库地址> <本地地址>

这样仓库会被 clone 到本地,并在主项目的根目录中新加一个文件.gitmodules,其中记录着:

[submodule "3rdparty/QHotkey"]
	path = 3rdparty/QHotkey
	url = https://github.com/Skycoder42/QHotkey.git
[submodule "3rdparty/glog"]
	path = 3rdparty/glog
	url = https://github.com/google/glog.git
[submodule "3rdparty/gflags"]
	path = 3rdparty/gflags
	url = https://github.com/gflags/gflags.git
[submodule "3rdparty/fmt"]
	path = 3rdparty/fmt
	url = https://github.com/fmtlib/fmt.git

另外,.git/config也会添加相关信息

[core]
	repositoryformatversion = 0
	filemode = true
	bare = false
	logallrefupdates = true
[submodule]
	active = .
[remote "origin"]
	url = https://github.com/ffiirree/Capturer.git
	fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
	remote = origin
	merge = refs/heads/master
[submodule "3rdparty/QHotkey"]
	url = https://github.com/Skycoder42/QHotkey.git
[submodule "3rdparty/fmt"]
	url = https://github.com/fmtlib/fmt.git
[submodule "3rdparty/gflags"]
	url = https://github.com/gflags/gflags.git
[submodule "3rdparty/glog"]
	url = https://github.com/google/glog.git

主项目的.git中会添加.git/modules/<SUBMODULE>目录,并对应原 submodule.git 中的内容,而 submodule 下的 .git 从文件夹转为一个文件,并记录指向上面主项目中添加的路径:

cat 3rdparty/glog/.git

gitdir: ../../.git/modules/3rdparty/glog

克隆主项目

git clone <REP> --recursive

或者

git clone <REP>

# 注册 submodule
git submodule init
# 拉取所有数据和检出子模块对应的commit
git submodule update

更新主项目

git pull

# --init --recursive 参数防止项目中添加了新的嵌套子模块
git submodule update --init --recursive

或者

git pull --recurse-submodules
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值