Git:使用git submodule构建项目工程

git submodule是git工具提供的一种特性,实现对项目依赖的其它代码仓库的管理。该特性主要是将相关的仓库建立一定的逻辑关系,并在顶级仓库中维护各个子仓库的相关信息,达到更好的管理依赖的代码库的目的。有了该特性就可以对项目代码仓库进行合理的划分,建立耦合度高的代码仓库,改善多人使用同一仓库开发提交代码时容易产生冲突的问题。同时可以更好的管理第三方代码仓库。git submodule是git工具提供的一种特性,实现对项目依赖的其它代码仓库的管理。该特性主要是将相关的仓库建立一定的逻辑关系,并在顶级仓库中维护各个子仓库的相关信息,达到更好的管理依赖的代码库的目的。有了该特性就可以对项目代码仓库进行合理的划分,建立耦合度高的代码仓库,改善多人使用同一仓库开发提交代码时容易产生冲突的问题。同时可以更好的管理第三方代码仓库。

一、相关概念与原理

顶级仓库:也可以叫根仓库,用于管理git代码的最上一层仓库,用于代码的发布;

父仓库:子仓库的父仓库,源于管理多个子仓库,顶级仓库就是其子仓库的父仓库;

子仓库:每一个被添加到父仓库的仓库都被称为父仓库的子仓库;

绑定关系:父仓库与其子仓库(版本号)的关系。一旦绑定关系确定,在不修改绑定关系的前提下,检出父仓库并归位(更新)子仓库,子仓库的版本号是固定的。下面详细描述绑定关系的原理。

1、绑定关系

大多应用与模块间的引用。例如,平台组发布D驱动仓库,其中D1、D2是相继两个版本。项目组S需要使用D仓库与release仓库R进行绑定。当前Release仓库含有R1、R2两个版本。在R2的版本上,R加入子仓库D,并R与D2进行绑定。紧接着,平台组在D仓库D2基础上发布了D3版本。R仓库每次检出的时候,更新后的子仓库都是D2版本,而不是D3,因为绑定关系是R&D2,和D3没有关系。也可以重新进行绑定,即R与D3进行绑定。以后R仓库每次检出的时候,更新后的子仓库都是D3版本。
顶层仓库可以绑定多个子仓库,绑定关系类似一棵树,除了树根以外,每个节点都是一个版本号。绑定关系确定了,这个树的各节点的值就确定了。

2、父子仓库

父仓库中可以有子仓库,可以有多个子仓库。子仓库中也可以有子仓库。

二、首次将父仓库与子仓库进行绑定

git submodule提供了一系列用于管理子仓库的命令,通过这一系列命令并结合git相关命令完成子仓库的管理工作。
1、添加子仓库
指令:

git submodule add Git_URL child_dir

解释:

  1. 指令含义:将子仓库的信息添加到父仓库的.gitmodules文件,并在父仓库的工作副本创建用于管理子仓库工作副本的目录。
  2. .gitmodules:在父仓库的根目录下,用于管理子仓库的路径。
  3. Git_URL: 指定子仓库的地址,比如http://172.0.20.254/gerrit/platform/web/uniweb
  4. child_dir: 在父仓库工作副本中用于管理子仓库工作副本的目录,必须是父仓库中不存在的目录。

特别注意:

child_dir目录千万不能手动创建,只能通过上述指令(自动)创建。如果执行指令前路径child_dir已存在,该指令会执行失败。需要手动删除后再试。
示例:

/* 以在web路径下添加uniweb子仓库为例 */ git submodule add
http://172.0.20.254/gerrit/platform/web/uniweb web/uniweb

2、下载并初始化子仓库

初始化子仓库,并下载代码。init和update后面,可直接跟子仓库的目录名。

git submodule init
git submodule update

这两行命令也可以合并为一行:

git submodule update --init

3、受控特定版本子仓库(绑定)

可能最新代码或默认分支(master)不是我们要绑定的版本,需要对子仓库进行切换分支和版本。

cd web/uniweb
git checkout BRANCH_1
git reset --hard Commit-ID_1
cd -
git add web/uniweb
git commit

三、日常使用

1、子仓库有变动

注意:母仓库是M,子仓库是A。A包含在M工程中以submodule形式存在。在如gerrit开发方式中,直接在M中的A目录内修改是无法push到远程仓库。正确做法是:单独clone出A仓库,修改,提交,push,合并到远端仓库。再在M中更新A这个submodule。
如果子仓库本地有变动,那么在父仓库下,执行git status可以看到如下几种情况:

#       modified:   child_dir (new commits)

上面的结果表示,子仓库与父仓库不在当前绑定关系中。子仓库的版本,要么是更旧了,要么是更新了。

#       modified:   child_dir (untracked content)

上面的结果表示子仓库中,有未受控的内容(Untracked)。

#       modified:   api_1 (modified content)

上面的结果表示子仓库中,有受控的文件被修改。

2、重新绑定

父仓库和子仓库的绑定关系需要重新确定,即,子仓库有更新,父仓库以后都要使用新版的子仓库代码。
在子仓库的目录中,切换到目标分支,拉下最新代码(如果有必要)。切换到目标版本(不一定是更新的版本)。

cd web/uniweb
git checkout BRANCH
git pull
git reset --hard Target_Commit_ID
cd -
git add web/uniweb
git commit

3、绑定关系查看

git submodule status
git submodule status --recursive     #包含上面的情况,也显示子仓库中子仓库的绑定情况

版本号之前的符号,“-”表示仓库检出的时候,还没有执行git submodule update;“+”表示子仓库版本与父仓库绑定关系不符。“ ”表示正常。

4、绑定关系归位

当前可能的状况是:子仓库使用了更新/更旧的版本,或者父仓库更新后,子仓库尚未同步。

git submodule update

四、注意事项

  1. 1.子仓库中无法将代码pushgerrit。(因为子仓库是submodule update下来的,不是clone下来的。clone下来带有Gerrit认证)
  2. 2.git submodule update后,所有的子仓库都处于(no branch)分支,不要害怕,只要git log的版本号没问题就行。
  3. 3.子仓库与父仓库的绑定关系中,子仓库的版本不一定是最新版,也不一定是master
  4. 4.当父仓库有新提交时,如绑定关系未发生变化,父仓库新版本下,子仓库内容(git submodule update后)不变。

五、删除子仓库

当顶级仓库不在需要子仓库代码时,应该及时解除顶级仓库和子仓库的关系。
四个步骤:

(1)删除.gitmodules文件中相关的子模块条目

(2)删除项目中子模块目录

(3)删除.git/modules中子模块文件夹

(4)删除.git/config文件中子模块相关条目

执行过程为:

一、删除子模块
	git rm --cache(会保留本地文件,只会删除.gitsubmodel文件中的子模块)
	rm -rf 子模块
或者
	git rm -rf 子模块(删除掉子模块-是将.gitsubmodule文件中模块删除,并且不会保留本地文件)
二、删除git中对应模块内容
(1)删除配置
	vi .git/config (删除对应模块的内容)
(2)删除git中缓存
	cd .git/module/
	rm 对应模块

或者

(1)git submodule deinit 子模块(手动实验了一下,执行这个命令之后.gitmodules文件并不会改变, 只是清空了子模块文件夹,子模块文件夹本身并不会被删除,并且会清空 .git/config文件中子模块相关条目)

(2)删除项目中子模块目录

(3)删除.git/modules中子模块文件夹

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

绛洞花主敏明

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值