Git——子模块(submodule)

2.1 常用命令

git clone <repository> --recursive 递归的方式克隆整个项目
git submodule add <repository> <path> 添加子模块
git submodule init 初始化子模块
git submodule update 更新子模块
git submodule foreach git pull 拉取所有子模块

项目包含由多个子模块,每个子模块是一个独立的 Git 仓库,子模块还允许继续嵌套包含子模块。 例如,主工程依赖 common、framework、react_native 等多个子模块,而 react_native 子模块又依赖 node_modules、HFCommon、HFModules 等多个嵌套子模块。

3.2 git submodule添加子模块

Git 提供了 submodule 来支持子模块的需求,使用它可以很方便的将多个独立仓库包含到同一个主工程中:

$ git init
$ git submodule add http://xxx.xxx/common.git
$ git submodule add http://xxx.xxx/framework.git

Git submodule 还支持嵌套添加子模块:

$ git submodule add http://xxx.xxx/react_native.git
$ cd react_native
$ git submodule add http://xxx.xxx/HFCommon.git
$ git submodule add http://xxx.xxx/HFModules.git
$ git submodule add http://xxx.xxx/node_modules.git

3.3 Git submodule 使用风险
通过子模块,这些子模块既可以各自独立的修改和提交代码,又可以将改动作用到依赖它的父工程。这听起来是个很棒的特性,然而 Git submodule 也存在着一些让人抓狂的坑。

首先,主工程并不直接跟踪子模块的代码,而仅仅只跟踪子模块的 commit id 的改动。在执行 git submodule update 更新子模块代码时,Git 就是根据主工程所维护的 commit id 来更新子模块到指定状态的。

bash-3.2$ git diff react_native
diff --git a/react_native b/react_native
index 3a9c5b1..ad68a28 160000
--- a/react_native
+++ b/react_native
@@ -1 +1 @@
-Subproject commit 3a9c5b14c45b199e2e6863d2b6da22dabc2a54f5
+Subproject commit ad68a28c13d4196df531c7df8523d07358288297
(END)

因此,如果你只在子模块中修改并提交了代码,而没有到主工程上面再把子模块的 commit id 提交一下,其他人拉取工程代码的时候会发现子模块的代码依然停留在老的 commit id 所指向的状态。对于嵌套子模块,这种工作尤为繁琐,提交代码后要逐层往上提交 commit id ,否则其他人无法正确更新代码。
其次,如前面所说,使用 git submodule update 更新子模块后,子模块将被切换到一个指向父工程维护的 commit id 所指定的游离状态:

bash-3.2$ git submodule update react_native
bash-3.2$ cd react_native
bash-3.2$ git branch
* (detached from 3a9c5b1)
master
jilin
TaiShan

一旦代码处于游离分支,你就要时刻警惕在游离分支上的提交有没有即时合并到非游离分支上。如果你直接在游离分支上开发并提交了代码,之后在父工程里再次 git submodule update ,你所有未合并的提交都会丢失!

最后还有一个非常麻烦,但也极容易出现的问题:如果团队里有人只提交了主工程该子模块的 commit id ,却忘了进入该模块提交模块真正的代码,那么当推送到中央仓库之后,其他人就会因为找不到与该 commit id 对应的代码而无法正确更新代码:

bash-3.2$ git submodule update
error: pathspec 'ad68a28c13d4196df531c7df8523d07358288297' did not match any file(s) known to git.
Did you forget to 'git add'?
Unable to checkout 'ad68a28c13d4196df531c7df8523d07358288297' in submodule path 'react_native'

对于熟练的用户,这些坑自然可以轻松越过。但考虑到团队里大都是 Git 新手,我们发现子模块的引入对他们造成了很大的负担,频繁出现子模块代码没有更新到最新状态,或者更新出错的情况。

3.4 子模块的更新
子模块的维护者提交了更新后,使用子模块的项目必须手动更新才能包含最新的提交。
在项目中,进入到子模块目录下,执行 git pull更新,查看git log查看相应提交。
完成后返回到项目目录,可以看到子模块有待提交的更新,使用git add,提交即可。

3.5 删除子模块
有时子模块的项目维护地址发生了变化,或者需要替换子模块,就需要删除原有的子模块。
删除子模块较复杂,步骤如下:

rm -rf 子模块目录 删除子模块目录及源码
vi .gitmodules 删除项目目录下.gitmodules文件中子模块相关条目
vi .git/config 删除配置项中子模块相关条目
rm .git/module/* 删除模块下的子模块目录,每个子模块对应一个目录,注意只删除对应的子模块目录即可

执行完成后,再执行添加子模块命令即可,如果仍然报错,执行如下:

git rm --cached 子模块名称

4.2 忽略 Git submodule
首先 .gitmodules 文件只是一个初始化配置。当你执行 git submodule init 时,git 会从 .gitmodules 读取信息来操作 .git/ 目录下的文件,比如修改 .git/config 以及修改 .git/modules/ 目录等操作。
存在一种使用场景,一个很大的项目下有些 submodule 项目不能让某些开发者访问。那么执行 git submodule update 会报错导致中断。
你可以忽略那些没有访问权限的子项目。假设有个名叫 xxx 的 submodule。
那么在 git submodule init 之后,修改 .git/config 文件,修改 active=false 和 ignore=all 即可。即:

[submodule "xxx"]
        url = git@github.com:zzz/xxx.git
        active = false
        ignore = all

之后的 git submodule 操作都会忽略掉 xxx 项目了。
这些配置可以通过 git help config 来找到,比如搜索 submodule..ignore。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,402评论 6 499
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,377评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,483评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,165评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,176评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,146评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,032评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,896评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,311评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,536评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,696评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,413评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,008评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,815评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,698评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,592评论 2 353

推荐阅读更多精彩内容

  • 什么是Git 子模块 开发中我们可能会遇到:某个工作中的项目需要包含并使用另一个项目。 可能是第三方库,也可能是独...
    一瓣山河阅读 10,992评论 0 8
  • 使用场景 当项目越来越庞大之后,不可避免的要拆分成多个子模块,我们希望各个子模块有独立的版本管理,并且由专门的人去...
    梅_梅阅读 368评论 0 1
  • 经常有这样的事情,当你在一个项目上工作时,你需要在其中使用另外一个项目。也许它是一个第三方开发的库或者是你独立开发...
    HongXunPan阅读 2,413评论 0 2
  • 目录 建立仓库1.1 创建主仓库1.2 创建子仓库 提交内容2.1 提交到主工程的仓库2.2 提交到子模块的仓库 ...
    SunnyZhou1024阅读 1,147评论 1 5
  • 做为一名程序员,大家对 ** Git ** 肯定都不陌生,最近项目中用到了 Git 子模块,今天,给大家讲一下 *...
    rangel阅读 2,016评论 5 6