欢迎任何形式的转载,转载请保留原文连接:juejin.cn/post/694825…java
为啥要用 git submodule,以及为啥不使用 git 仓库直接嵌套的形式 ?git
本文主要讲解 git submodule 使用与教程,目的有如下几点:github
注:为了方便查阅经常使用操做以及对应命令,文章章节顺序非友好的学习顺序,其中教程巨长放到最后了,若是教程以前的内容看不明白,建议过一遍教程shell
# 查看 submodules
# 结果的 hash 前不带符号说明该 module 正常且提交版本同步(提交版本同步指主项目记录提交版本与子模块当前提交版本一致)
# 结果的 hash 前带 - 号说明该 module 未初始化
# 结果的 hash 前带 + 号说明该 module 版本未同步
git submodule
git submodule status
# 初始化 modules,重复初始化无影响,例子中后跟 rxjava 为指定初始化某个 module 的名称(下同)
git submodule init
git submodule init rxjava
# 版本未同步时,检出 modules,保证检出的版本与主项目匹配,但子 module 会建立临时分支
git submodule update
git submodule update rxjava
# 添加 submodule,例子中后跟 rxjava 为该 module 名称与目录名
git submodule add https://github.com/ReactiveX/RxJava.git
git submodule add https://github.com/ReactiveX/RxJava.git rxjava
# 强制添加 submodule(仅用于 git submodule 没有正确的显示某个 module)
git submodule add --force --name rxjava https://github.com/ReactiveX/RxJava.git
# 从新 clone 项目(含 clone 全部子项目)方式一
git clone --recursive https://github.com/ReactiveX/RxJava.git
# 从新 clone 项目(含 clone 全部子项目)方式二,依次执行如下命令
git clone https://github.com/ReactiveX/RxJava.git
git submodule init
git submodule update
# 遍历全部 submodule
# git submodule foreach 其余命令,如:
git submodule foreach git pull
git submodule foreach ls -l
复制代码
主项目拉取,且有新的 submodule(就是存在未初始化的)浏览器
git pull
git submodule init
git submodule update [新 module 名称]
复制代码
其余说明:缓存
git pull
便可。若是想让提交版本同步,主项目使用 git submodule update rxjava
git clone
(方式二)要先初始化,再检出,这样才能正常使用本地仓库不废弃的状况下,对某个 submodule 进行删除、修更名称、修改仓库地址操做,但除了修改仓库地址,其余人的远程仓库是基本完蛋了,须要从新 clonebash
删除 submodulemarkdown
git reset --hard HEAD
命令,再次强调全部修改都已提交再操做git submodule
的结果没有要删除的# 假设 submodule 名称为 subA
# 1. 必须,git rm -r --cached subA
# 2. 必须,rm -rf subA/,或手动删除对应目录
# 3. 必须,修改【.gitmodules】文件内容:去除被删除的 submodule 内容
# 4. 非必须,修改【.git/config】文件内容:去除被删除的 submodule 内容
# 5. 非必须,删除【.git/modules】目录下对应 submodule 目录
复制代码
重命名 submodule 目录工具
git rm -r --cached subA
命令,以及 git submodule add
命令更改 submodule 远程仓库地址oop
# 1. 修改【.gitmodules】文件对应仓库地址:只影响远程仓库
# 2. 修改【.git/config】文件对应仓库地址:额,改不改无所谓
# 3. 进入子模块,使用 `git remote` 命令,更新远程仓库地址
复制代码
关于远程仓库
关于本地仓库
git submodule update
检出时,保证检出的版本与主项目匹配,但子 module 会建立临时分支最主要的是主项目的【.gitmodules】文件,内容以下,觉得比较简单就不解释了
[submodule "subA"]
path = subA
url = /cygdrive/e/submodule/repo/subA.git
[submodule "subB"]
path = subB
url = /cygdrive/e/submodule/repo/subB.git
复制代码
关于本地仓库,对比添加 submodule 先后:
git submodule init
后更新git submodule update
后出现# 【子模块/.git】文件
gitdir: ../.git/modules/subA
复制代码
# 【.git/config】文件,下列[submodule "subA"]块是多出来的
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
[remote "origin"]
url = /cygdrive/e/submodule/repo/main.git
fetch = +refs/heads/*:refs/remotes/origin/*
[submodule "subA"]
active = true
url = /cygdrive/e/submodule/repo/subA.git
[submodule "subB"]
active = true
url = /cygdrive/e/submodule/repo/subB.git
复制代码
$ ll .git/modules/
总用量 8
drwxrwxr-x+ 1 Administrator None 0 4月 2 15:41 subA/
drwxrwxr-x+ 1 Administrator None 0 4月 2 15:41 subB/
复制代码
如下是 git submodule 详细使用教程
为方便验证与测试,这里提供测试环境搭建过程
建立(本地性质的)远程仓库
# 建立(本地性质的)远程仓库与本地仓库目录
$ mkdir repo
$ mkdir project
# 进入远程仓库目录,创建主项目远程仓库(main.git)以及,若干个子模块远程仓库(subA.git)
$ cd repo
$ git --git-dir=main.git init --bare
$ git --git-dir=subA.git init --bare
$ git --git-dir=subB.git init --bare
$ ll
总用量 16
drwxrwxr-x+ 1 Administrator None 0 4月 2 14:53 main.git/
drwxrwxr-x+ 1 Administrator None 0 4月 2 14:53 subA.git/
drwxrwxr-x+ 1 Administrator None 0 4月 2 14:53 subB.git/
# 获取远程仓库地址,用来 clone 项目
$ cd main.git
$ pwd
/cygdrive/e/submodule/repo/main.git
# 同理其余子模块远程仓库地址
/cygdrive/e/submodule/repo/subA.git
/cygdrive/e/submodule/repo/subB.git
复制代码
远程仓库初始提交,目的为了让每一个远程仓库都有分支,以及提交记录
# 在 repo 目录下 clone 代码
$ cd ../
$ pwd
/cygdrive/e/submodule/repo
$ git clone main.git
$ ll
总用量 16
drwxrwxr-x+ 1 Administrator None 0 4月 2 15:21 main/
drwxrwxr-x+ 1 Administrator None 0 4月 2 14:53 main.git/
drwxrwxr-x+ 1 Administrator None 0 4月 2 14:53 subA.git/
drwxrwxr-x+ 1 Administrator None 0 4月 2 14:53 subB.git/
# 建立任意文件,并作初始化提交,并推送到远程
$ cd main
$ touch init
$ git add .
$ git commit -m "main init"
$ git push
$ git branch
* master
$ git log --oneline
468894f (HEAD -> master, origin/master) main init
# 到这里上述 main.git 远程仓库就有一个 master 分支,以及一个提交记录了
# 既然已近作好推送了,就能够删除这个用来作初始化的临时本地仓库了
$ cd ..
$ rm -rf main
# 其余远程仓库,按上述同操做便可,如下为各个远程仓库首次提交
468894f (HEAD -> master, origin/master) main init
5ae8df5 (HEAD -> master, origin/master) subA init
6bf24b8 (HEAD -> master, origin/master) subB init
复制代码
复制主项目远程仓库,用来对比添加 submodule 先后,远程仓库的变化
从远程仓库 clone 到项目目录下的本地仓库
# 主项目 clone,多 clone 一个是为了对比
$ cd ../project
$ git clone /cygdrive/e/submodule/repo/main.git
$ git clone /cygdrive/e/submodule/repo/main.git main_copy
复制代码
添加子 module(如下简称子模块)
# 往主项目里添加 submodule,注:一个一个来,以便分开 commit,方便后续演示
$ cd main
$ git submodule add /cygdrive/e/submodule/repo/subA.git
正克隆到 '/cygdrive/e/submodule/project/main/subA'...
完成。
warning: .gitmodules 中的 LF 将被 CRLF 替换。
在工做区中该文件仍保持原有的换行符
# 添加后结果
$ ll
总用量 0
-rw-rw-r--+ 1 Administrator None 0 4月 2 15:37 init
drwxrwxr-x+ 1 Administrator None 0 4月 2 15:37 subA/
$ git status
位于分支 master
您的分支与上游分支 'origin/master' 一致。
要提交的变动:
(使用 "git reset HEAD <文件>..." 以取消暂存)
新文件: .gitmodules
新文件: subA
$ ll -a subA/
总用量 1
drwxrwxr-x+ 1 Administrator None 0 4月 2 15:37 ./
drwxrwxr-x+ 1 Administrator None 0 4月 2 15:38 ../
-rw-rw-r--+ 1 Administrator None 29 4月 2 15:37 .git
-rw-rw-r--+ 1 Administrator None 0 4月 2 15:37 init
# 主项目提交本次添加 submodule 的结果
$ git add .
$ git commit -m "添加 submodule:subA"
[master 7ada136] 添加 submodule:subA
2 files changed, 4 insertions(+)
create mode 100644 .gitmodules
create mode 160000 subA
# 同理添加另外一个 submodule,最后提交记录与 submodule 记录以下
$ git log --oneline
31287e4 (HEAD -> master) 添加 submodule:subB
7ada136 添加 submodule:subA
468894f (origin/master, origin/HEAD) main init
$ git submodule
5ae8df5a1fd55d31b0fc7e8bdf7d02fb7591f4bd subA (heads/master)
6bf24b87a83ee2621e9b9aaf93b6d0f4f2b81638 subB (heads/master)
复制代码
对比 main 和 main_copy(没有 submodule)可知
git submodule init
后更新git submodule update
后出现$ cat .gitmodules
[submodule "subA"]
path = subA
url = /cygdrive/e/submodule/repo/subA.git
[submodule "subB"]
path = subB
url = /cygdrive/e/submodule/repo/subB.git
$ cat subA/.git
gitdir: ../.git/modules/subA
$ cat .git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
[remote "origin"]
url = /cygdrive/e/submodule/repo/main.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
[submodule "subA"]
url = /cygdrive/e/submodule/repo/subA.git
active = true
[submodule "subB"]
url = /cygdrive/e/submodule/repo/subB.git
active = true
$ ll .git/modules/
总用量 8
drwxrwxr-x+ 1 Administrator None 0 4月 2 15:41 subA/
drwxrwxr-x+ 1 Administrator None 0 4月 2 15:41 subB/
复制代码
若是远程仓库使用的是真实的远程仓库,则使用浏览器访问主项目时,就能够发现主项目存在 submodule 目录,并点击该目录能够跳转到 submodule 对应的远程仓库
到此对比远程仓库添加 submodule 先后,能够发现除了提交记录与 HEAD 指证外,其余文件并未发生变化,因此主项目的 submodule 记录仅取决于主项目下的【.gitmodules】文件内容
删除 submodule 的方式有两种
方式一:只修改【.gitmodules】文件,而后推送远程仓库,再从新 clone,本来地仓库不要了
git clone
新开一个本地仓库# 原【.gitmodules】内容
[submodule "subA"]
path = subA
url = /cygdrive/e/submodule/repo/subA.git
[submodule "subB"]
path = subB
url = /cygdrive/e/submodule/repo/subB.git
# 删除后【.gitmodules】内容
[submodule "subA"]
path = subA
url = /cygdrive/e/submodule/repo/subA.git
复制代码
方式二:本地仓库正常删除 submodule,而后推送远程仓库,本来地仓库依然可使用
必须,清除 submodule 缓存记录
git reset --hard HEAD
命令,再次强调全部修改都已提交再操做git submodule
结果没有要删除的$ git rm -r --cached subA
rm 'subA'
# 上述命令结果验证
$ git submodule
5ae8df5a1fd55d31b0fc7e8bdf7d02fb7591f4bd subA (heads/master)
复制代码
必须,删除 submodule 文件夹,即 subA 文件夹,对应命令以下,不过建议手动删除
$ rm -rf subA/
复制代码
必须,修改【.gitmodules】文件内容:去除被删除的 submodule 内容
# 原内容
[submodule "subA"]
path = subA
url = /cygdrive/e/submodule/repo/subA.git
[submodule "subB"]
path = subB
url = /cygdrive/e/submodule/repo/subB.git
# 删除后内容
[submodule "subA"]
path = subA
url = /cygdrive/e/submodule/repo/subA.git
复制代码
非必须,修改【.git/config】文件内容:去除被删除的 submodule 内容
# 原内容
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
[submodule]
active = .
[remote "origin"]
url = /cygdrive/e/submodule/repo/main.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
[submodule "subA"]
url = /cygdrive/e/submodule/repo/subA.git
[submodule "subB"]
url = /cygdrive/e/submodule/repo/subB.git
# 删除后内容
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
[submodule]
active = .
[remote "origin"]
url = /cygdrive/e/submodule/repo/main.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
[submodule "subA"]
url = /cygdrive/e/submodule/repo/subA.git
复制代码
非必须,删除【.git/modules】目录下对应 submodule 目录
没有好办法,全部的方法,本质都是先删除,再从新添加
git rm -r --cached subA
命令,以及 git submodule add
命令如下操做是错误的:
这里说的是修改只修改远程仓库地址,不修改子模块名称的状况
背景:原来的 /cygdrive/e/submodule/repo/subA.git
远程仓库迁移到 /cygdrive/e/submodule/subA.git
更改步骤说明
# 1. 修改【.gitmodules】文件对应仓库地址:只影响远程仓库
# 2. 修改【.git/config】文件对应仓库地址:额,改不改无所谓
# 3. 进入子模块,使用 `git remote` 命令,更新远程仓库地址
复制代码
这里演示多人共同开发主项目时,其中一人添加了 submodule
pull 主项目,并查看日志
$ cd main_copy
$ git pull
$ git log --oneline
31287e4 (HEAD -> master, origin/master, origin/HEAD) 添加 submodule:subB
7ada136 添加 submodule:subA
468894f main init
复制代码
查看 submodule 记录、子模块内容、【.gitmodules】文件、【.git/config】文件、【.git/modules】目录、子模块日志
$ git submodule
-5ae8df5a1fd55d31b0fc7e8bdf7d02fb7591f4bd subA
-6bf24b87a83ee2621e9b9aaf93b6d0f4f2b81638 subB
$ ll -a subA subB
subA:
总用量 0
drwxrwxr-x+ 1 Administrator None 0 4月 2 17:36 ./
drwxrwxr-x+ 1 Administrator None 0 4月 2 17:36 ../
subB:
总用量 0
drwxrwxr-x+ 1 Administrator None 0 4月 2 17:36 ./
drwxrwxr-x+ 1 Administrator None 0 4月 2 17:36 ../
$ cat .gitmodules
[submodule "subA"]
path = subA
url = /cygdrive/e/submodule/repo/subA.git
[submodule "subB"]
path = subB
url = /cygdrive/e/submodule/repo/subB.git
$ cat .git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
[remote "origin"]
url = /cygdrive/e/submodule/repo/main.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
$ ll .git/modules
/bin/ls: 没法访问'.git/modules': No such file or directory
$ cd subA
$ git log --oneline
31287e4 (HEAD -> master, origin/master, origin/HEAD) 添加 submodule:subB
7ada136 添加 submodule:subA
468894f main init
$ cd ..
复制代码
如上,发现如下几个问题
git submodule
的结果前面带[-]号这些问题都是由于子模块并无初始化、检出致使的
git submodule
的结果前面带[-]号就是表示该 submodule 未初始化# 初始化所有 submodule,重复初始化无反应
$ git submodule init
子模组 'subA'(/cygdrive/e/submodule/repo/subA.git)已对路径 'subA' 注册
子模组 'subB'(/cygdrive/e/submodule/repo/subB.git)已对路径 'subB' 注册
$ git submodule init
$ git submodule init subA
$ git submodule
5ae8df5a1fd55d31b0fc7e8bdf7d02fb7591f4bd subA
6bf24b87a83ee2621e9b9aaf93b6d0f4f2b81638 subB
# 检出全部 submodule,重复检出无反应
$ git submodule update
正克隆到 '/cygdrive/e/submodule/project/main_copy/subA'...
完成。
正克隆到 '/cygdrive/e/submodule/project/main_copy/subB'...
完成。
Submodule path 'subA': checked out '5ae8df5a1fd55d31b0fc7e8bdf7d02fb7591f4bd'
Submodule path 'subB': checked out '6bf24b87a83ee2621e9b9aaf93b6d0f4f2b81638'
$ git submodule update
$ git submodule update subA
$ git submodule
5ae8df5a1fd55d31b0fc7e8bdf7d02fb7591f4bd subA
6bf24b87a83ee2621e9b9aaf93b6d0f4f2b81638 subB
$ cd subA
$ git log --oneline
5ae8df5 (HEAD, origin/master, origin/HEAD, master) subA init
cd ..
复制代码
通过初始化和检出,子模块就能够正常使用了
git submodule
的结果前面就不带任何符号了两种方式,一种是是直接 clone 项目,而后初始化、检出
$ git clone /cygdrive/e/submodule/repo/main.git main_new
正克隆到 'main_new'...
完成。
$ git submodule init
子模组 'subA'(/cygdrive/e/submodule/repo/subA.git)已对路径 'subA' 注册
子模组 'subB'(/cygdrive/e/submodule/repo/subB.git)已对路径 'subB' 注册
$ git submodule update
正克隆到 '/cygdrive/e/submodule/project/main_new/subA'...
完成。
正克隆到 '/cygdrive/e/submodule/project/main_new/subB'...
完成。
Submodule path 'subA': checked out '5ae8df5a1fd55d31b0fc7e8bdf7d02fb7591f4bd'
Submodule path 'subB': checked out '6bf24b87a83ee2621e9b9aaf93b6d0f4f2b81638'
复制代码
另一种是 clone 时添加 --recursive
选项直接一步到位
$ git clone --recursive /cygdrive/e/submodule/repo/main.git main_new_02
正克隆到 'main_new'...
完成。
子模组 'subA'(/cygdrive/e/submodule/repo/subA.git)已对路径 'subA' 注册
子模组 'subB'(/cygdrive/e/submodule/repo/subB.git)已对路径 'subB' 注册
正克隆到 '/cygdrive/e/submodule/project/main_new/subA'...
完成。
正克隆到 '/cygdrive/e/submodule/project/main_new/subB'...
完成。
Submodule path 'subA': checked out '5ae8df5a1fd55d31b0fc7e8bdf7d02fb7591f4bd'
Submodule path 'subB': checked out '6bf24b87a83ee2621e9b9aaf93b6d0f4f2b81638'
复制代码
初始化,以及检出以后,误把子模块删除。这里先说下结论
git submodule update
,但这种检出会建立一个临时分支# 缺失子模块,不影响主项目 diff
$ rm -rf subB/
$ git status
位于分支 master
您的分支与上游分支 'origin/master' 一致。
无文件要提交,干净的工做区
# 缺失子模块,一样不影响主项目 submodule 记录
$ git submodule
d8346a82a2ba13077d7f25124239ac0d3db5920c subA (heads/master)
6bf24b87a83ee2621e9b9aaf93b6d0f4f2b81638 subB
# 缺失子模块,重复初始化不起做用
$ git submodule init
$ ll
总用量 0
-rw-rw-r--+ 1 Administrator None 0 4月 2 17:04 init
drwxrwxr-x+ 1 Administrator None 0 4月 2 17:26 subA/
# 缺失子模块,无效且错误作法:新建对应文件夹,而后在对应文件夹里 pull,从结果能够看出日志并非子模块的日志
$ mkdir subB
$ cd subB/
$ gitlog
* 0e3354b 2021-04-02 18:42:00 | (HEAD -> other, origin/master, origin/HEAD, master)submodule subA 提交记录更更新 <jefshi>
* 31287e4 2021-04-02 17:10:54 | 添加 submodule:subB <jefshi>
* 7ada136 2021-04-02 17:05:20 | 添加 submodule:subA <jefshi>
* 468894f 2021-04-02 15:24:36 | main init <jefshi>
# 缺失子模块,从新检出,但子模块是建立一个临时分支
$ git submodule update
Submodule path 'subB': checked out '6bf24b87a83ee2621e9b9aaf93b6d0f4f2b81638'
$ ll
总用量 0
-rw-rw-r--+ 1 Administrator None 0 4月 2 17:04 init
drwxrwxr-x+ 1 Administrator None 0 4月 2 17:26 subA/
drwxrwxr-x+ 1 Administrator None 0 4月 2 20:50 subB/
$ cd subB
$ git branch
master
* (头指针分离于 6bf24b8)
$ cd ..
复制代码
进入子模块目录进行修改并提交
$ cd main/subA
$ touch first
$ git add .
$ git commit -m "subA:第一次修改"
$ git push
$ git log --oneline
d8346a8 (HEAD -> master) subA:第一次修改
5ae8df5 (origin/master, origin/HEAD) subA init
复制代码
主项目查看差别,提交并查看 submodule。这里先说下结论
git submodule
的结果前面带[+]号,表示主项目记录的提交版本与对应 submodule 的提交记录不一致# 子模块提交记录同步前
$ git submodule
+d8346a82a2ba13077d7f25124239ac0d3db5920c subA (heads/master)
6bf24b87a83ee2621e9b9aaf93b6d0f4f2b81638 subB (heads/master)
$ cd ..
$ git status
位于分支 master
您的分支与上游分支 'origin/master' 一致。
还没有暂存以备提交的变动:
(使用 "git add <文件>..." 更新要提交的内容)
(使用 "git checkout -- <文件>..." 丢弃工做区的改动)
修改: subA (新提交)
$ git add .
$ git commit -m "submodule subA 提交记录更更新"
[master 0e3354b] submodule subA 提交记录更更新
1 file changed, 1 insertion(+), 1 deletion(-)
$ git submodule
d8346a82a2ba13077d7f25124239ac0d3db5920c subA (heads/master)
6bf24b87a83ee2621e9b9aaf93b6d0f4f2b81638 subB (heads/master)
$ git push
复制代码
另外一个主项目(main_copy)从远程仓库更新上述操做。这里先说下结论
git pull
只会更新主项目,不会更新子模块,反过来也是如此git submodule update
git submodule foreach git pull
git pull
操做# 更新前,主项目是无感知的
cd ../main_copy
$ git submodule
5ae8df5a1fd55d31b0fc7e8bdf7d02fb7591f4bd subA (heads/master)
6bf24b87a83ee2621e9b9aaf93b6d0f4f2b81638 subB (heads/master)
# 更新后,能够看到提交版本不一致
$ git pull
$ git log --oneline
0e3354b (HEAD -> master, origin/master, origin/HEAD) submodule subA 提交记录更更新
31287e4 添加 submodule:subB
7ada136 添加 submodule:subA
468894f main init
$ git submodule
+5ae8df5a1fd55d31b0fc7e8bdf7d02fb7591f4bd subA (heads/master)
6bf24b87a83ee2621e9b9aaf93b6d0f4f2b81638 subB (heads/master)
# 更新子模块方式一
$ git submodule update
Submodule path 'subA': checked out 'd8346a82a2ba13077d7f25124239ac0d3db5920c'
$ cd subA
$ git branch
master
* (头指针分离于 d8346a8)
# 子模块还原
$ git checkout master
$ git reset --hard HEAD
$ cd ..
# 更新子模块方式二
$ git submodule foreach git pull
进入 'subA'
更新 5ae8df5..d8346a8
Fast-forward
first | 0
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 first
进入 'subB'
来自 /cygdrive/e/submodule/repo/subB
+ 4f6ad1c...6bf24b8 master -> origin/master (强制更新)
已是最新的。
$ cd subA
$ git log --oneline
d8346a8 (HEAD -> master, origin/master, origin/HEAD) subA:第一次修改
5ae8df5 subA init
cd ..
复制代码
关于主项目记录的提交版本与子模块不一致讨论,不一致有如下几种
新建一个分支,使 master 分支含有两个 submodule,另外一个分支只含有一个
$ git branch
* master
$ git log --oneline
0e3354b (HEAD -> master, origin/master, origin/HEAD) submodule subA 提交记录更更新
31287e4 添加 submodule:subB
7ada136 (onlySubA) 添加 submodule:subA
468894f main init
$ git submodule
d8346a82a2ba13077d7f25124239ac0d3db5920c subA (heads/master)
6bf24b87a83ee2621e9b9aaf93b6d0f4f2b81638 subB (heads/master)
$ git checkout -b onlySubA 7ada136
$ git log --oneline
7ada136 (HEAD -> onlySubA) 添加 submodule:subA
468894f main init
$ git branch
master
* onlySubA
$ git submodule
+d8346a82a2ba13077d7f25124239ac0d3db5920c subA (heads/master)
复制代码
这里 master 有两个 submodule,onlySubA 分支只有一个 submodule。接下来看下 onlySubA 分支的提交差别,以及一些相关文件。
这里先说下结论,能够看出在 onlySubA 分支上
$ git branch
master
* onlySubA
$ git status
位于分支 onlySubA
还没有暂存以备提交的变动:
(使用 "git add <文件>..." 更新要提交的内容)
(使用 "git checkout -- <文件>..." 丢弃工做区的改动)
修改: subA (新提交)
未跟踪的文件:
(使用 "git add <文件>..." 以包含要提交的内容)
subB/
$ cat .gitmodules
[submodule "subA"]
path = subA
url = /cygdrive/e/submodule/repo/subA.git
$ cat .git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
[remote "origin"]
url = /cygdrive/e/submodule/repo/main.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
[submodule "subA"]
url = /cygdrive/e/submodule/repo/subA.git
active = true
[submodule "subB"]
url = /cygdrive/e/submodule/repo/subB.git
active = true
$ ll .git/modules/
总用量 8
drwxrwxr-x+ 1 Administrator None 0 4月 2 20:35 subA/
drwxrwxr-x+ 1 Administrator None 0 4月 2 20:33 subB/
复制代码
因为切分支时多余的子模块文件夹并不会被删除。若是此时误操做把多余的子模块文件夹给提交了,分析下以后从新添加相同子模块的 submodule 的结果。这里先说下结论
# 背景
$ git status
位于分支 onlySubA
未跟踪的文件:
(使用 "git add <文件>..." 以包含要提交的内容)
subB/
# 误操做
$ git add .
$ git commit -m "误把不须要的子模块提交"
$ git status
位于分支 onlySubA
无文件要提交,干净的工做区
# 添加相同的子模块失败
$ git submodule add /cygdrive/e/submodule/repo/subB.git
'subB' already exists in the index
复制代码
背景:
# 背景:主项目两个分支,以及分支指向的提交记录(other 指向 31287e4)
$ git branch
* master
other
$ git log --oneline
0e3354b (HEAD -> master, origin/master, origin/HEAD) submodule subA 提交记录更更新
31287e4 (other) 添加 submodule:subB
7ada136 添加 submodule:subA
468894f main init
# 背景:子模块 subA 两个分支,以及分支指向的提交记录
$ cd subA
$ git branch
* master
subOther
$ git log --oneline
d8346a8 (HEAD -> master, origin/master, origin/HEAD) subA:第一次修改
5ae8df5 (subOther) subA init
$ cd ..
复制代码
上述主项目和子模块都是 master 分支,如今主项目切换到 other 分支,观察子模块分支状况,这里先说下结论
# 主项目切分支
$ git branch
* master
other
$ git checkout other
M subA
切换到分支 'other'
$ git submodule
+d8346a82a2ba13077d7f25124239ac0d3db5920c subA (heads/master)
6bf24b87a83ee2621e9b9aaf93b6d0f4f2b81638 subB (heads/master)
# 主项目切分支后,子模块分支状况
$ cd subA/
$ git branch
* master
subOther
复制代码
参考文献:
博客同步版本: