git submodule add git@github.com:walkerdu/draw_io.git submodules/draw_io执行完上述submodule add命令后,可以查看本地仓库的变化如下:
$git status On branch master Your branch is up to date with 'origin/master'. Changes to be committed: (use "git reset HEAD <file>..." to unstage) new file: .gitmodules new file: submodules/draw_io我们可以看到当前仓库的已经多了两个文件.gitmodules和submoudles/draw_io,且这「两个文件已经被自动加入了stage区域」;
$cat .gitmodules [submodule "submodules/draw_io"] path = submodules/draw_io // 存放路径 url = git@github.com:walkerdu/draw_io.git // submodule的url地址其中另外一个变化:submodules/draw_io在本地是add submodule后,clone下来的跟踪的项目draw_io的仓库;「但为什么上面git status提示的是他是一个new file呢」?下面研究一下原因:
$git commit -m 'init submodule' . [master 4894d7d] init submodule 2 files changed, 4 insertions(+) create mode 100644 .gitmodules create mode 160000 submodules/draw_io然后查看提交的内容如下:
/* 堆代码 duidaima.com */ $git show 4894d7d commit 4894d7dbde107741a0956bc018ad1e6ec1ca80b3 (HEAD -> master) Author: walkerdu <anonym_alias@163.com> Date: Thu May 12 15:31:43 2022 +0800 init submodule diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..df23d83 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "submodules/draw_io"] + path = submodules/draw_io + url = git@github.com:walkerdu/draw_io.git diff --git a/submodules/draw_io b/submodules/draw_io new file mode 160000 index 0000000..9b5dcda --- /dev/null +++ b/submodules/draw_io @@ -0,0 +1 @@ +Subproject commit 9b5dcdac92b0d0e07264ae22267814fd052d4560我们可以看到submodules/draw_io提交的内容是此跟踪项目的最新的commitid;所以我们得知,「对于submodule管理的模块,会将.gitmodules映射的本地存储路径进行忽略,将其最新的commitid作为文件内容在主仓库中进行跟踪管理」;
$git submodule update --remote ... From github.com:walkerdu/draw_io 9b5dcda..26b9e31 master -> origin/master Submodule path 'submodules/draw_io': checked out '26b9e31e0367c16894910f3ebce4e2d334a812da' $git status ... Changes not staged for commit: ... modified: submodules/draw_io (new commits)更新submodule后,主仓库里面可以发现跟踪的submodules/draw_io已经发生了变化;此时可以将最新的跟踪仓库的commitid的变化进行提交;这样项目就刷新了最新跟踪的submodule信息;我们此时看一下跟踪项目本地目录的状态:
$git status HEAD detached at 117e833 nothing to commit, working tree clean「为什么跟踪的submodule本地项目变成了detached状态呢」?这里看一下git submodule update命令的man,简单说一下;
$git config -f .gitmodules submodule.submodules/draw_io.branch develop $git status On branch develop Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: .gitmodules跟踪draw_io的develop分支,执行完修改后.gitmodules发生变化,如下:
[submodule "submodules/draw_io"] path = submodules/draw_io url = git@github.com:walkerdu/draw_io.git + branch = develop然后执行git submoudle update --remote就可以刷新主仓库跟踪的commitid到分支的最新提交上面;
「Git 2.34(Q4 2021)」版本及以后,在git clone --recurse-submodules拉取的仓库时,默认会设置git config --global submodule.recurse true,不需要再关心submodule的跟踪问题了;
通过git config --global push.recurseSubmodules=on-demand来配置;和上述含义一样;不过这里为什么不使用git config --global submodule.recurse true的设置呢?「看来submodule.recurse的配置不仅不对clone生效,在push的时候也不生效…」
git submodule foreachgit提供了可以在主项目中执行所有git命令来直接操作子项目的方式,命令:git submodule foreach 'git cmd',foreach可以遍历所有submodule,然后执行后面的git命令,如下查看子项目的所有分支:
$git submodule foreach 'git branch -av' Entering 'submodules/draw_io' * (HEAD detached at a62a01f) a62a01f change name master 117e833 [behind 4] update README.md remotes/origin/HEAD -> origin/master remotes/origin/develop a62a01f change name remotes/origin/master abe26b7 sync我们可以alias git-sf='git submodule foreach'来便捷的操作submodule;