前言
现在很多公司、个人都在使用git来实行代码管理,而submodule也是一个比较好用的功能,可以在项目的代码仓库中创建一个子模块的仓库,这样子模块的每次commit并不会影响整个项目的版本更替,当子模块的功能完成后再对整个子模块add/commit即可。
在git下如何创建submodule,网上随便搜一搜都有,命令如下:
git submodule add <same url as if you were just cloning> <some path>
git submodule update --init --recursive
因为一半情况下,本地本地创建repo,然后push,就可以有url进行添加配置。
但是如果采用gitolite进行git repo的管理,就出现问题了。
初识gitolite
首先,使用gitolite管理repo的一个特点就是:只有管理员能创建repo。
所以不能在本地通过git init、git add、git commit、 git push这一套流程来创建repo。
其次,gitolite是通过配置文件来创建repo的。如下:


图1是repo的配置文件,图2是配置的命令
如图完成服务端配置并commit修改之后,就有了test、subtest、sub1三个repo。
配置操作
假设我们的需求是将subtest、sub1两个repo添加成为test的submodule。假设repo的url前缀为sample.com,接着上面的操作进行处理。
1. "实例化"repo
cd test
git status
得到如图3

这时候需要进行一次commit,比如
touch 1
git add 1
git commit -1 'xx'
git push origin master
git status
然后可得到图4

对着subtest进行相应的操作(提交一次commit)
2. 配置submodule
在完成上述的操作之后,就可以正常进行submodule的add操作了
cd test
git submodule add git@sample.com:subtest subtest
git add ./
git commit -m 'add submodule subtest'
git push origin master
这样就ok了,在其他地方执行以下命令即可
git clone git@sample.com:test
git submodule init
git submodule update
得到本地仓库如图5/6


tips
- 1 不先进行repo "实例化"操作会怎样?
sub1是没有进行“实例化”操作的,对sub1进行submodule配置操作的话,结果如图7

而如图5所示,本地已有sub1的文件夹,却并不能成功添加,这发生了什么呢?
个人猜测:
通过修改配置脚本创建repo,就相当于类的声明,就是在概念上它存在,但并没有实体,无法被trace;所以需要实例化,而trace的依据就是commit id。
- 2 git sumodule init和git submodule update都做了什么?
在实现的时候,由于管理员和我对repo地址的映射不一致,所以在执行上述两条命令的时候,出现过问题,如图8

管理员将repo的地址git@sample.com映射为git了,而我也针对git@sample.com单独配置了私钥映射为gitabc,这样对于git我就没有不能正确解析为git@sample.com,也有没有访问权限了。
然而此时我已经执行过上面两条命令了,怎么拯救呢?
首先要修改图5中的.gitmodules文件,如图9

然后要修改test/.git/config文件,如图10

然后删除subtest,再执行上面两条命令就可以了,如图11,别忘了提交改动

所以对于上述两条命令所做的工作,
个人猜测
- git submodule add [url] [name]
将子repo的git信息添加到.gitmodules文件中 - git submodule init
根据.gitmodules将子repo添加到父repo的.git/config中 - git submodule update
根据.git/config获取子repo的最新代码
网友评论