赞
踩
子模块(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
改变了),这表明主项目依赖的 submodule
的commit
和此时 submodule
的 HEAD
不一致了,进入子项目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
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。