大型项目中常常由多人合作,项目中会有一些功能有专人维护,其他人员不需修改。在git中使用submodule功能可以不必关心他人维护的模块,大大提高开发效率。
为git仓库新增子module
项目中常常会用到其他人维护的模块,可采用如下方式新增子module。
添加子模块
1 | git submodule add <url> <path> # 添加远程子module,-b branch 才会写入分支信息,而且参数必须固定在add后 |
执行git status
会看到项目中多了一个.gitmodules
文件
可以每增加一个子module,.gitmodules
会增加一条内容:
1 | [submodule "modulename"] |
然后按git的工作流程将子module信息同步到远程仓库
更新子module仓库信息
1 | [submodule "modulename"] |
直接修改.gitmodules
中子仓库的上述任意信息。
仓库的.git/config
中相关信息不会被自动修改。需要执行这条命令更新。
1 | git submodule sync |
然后按git的工作流程将子module信息同步到远程仓库
下载子module
克隆项目后,默认子模块只有对应的空文件夹。需要在子项目中完成如下命令初始化和克隆子module
1 | git submodule init |
或者
1 | git submodule update --init --recursive |
批量更新子module
1 | git submodule foreach git pull |
删除子module
1 | git rm -rf --caches <path> |
或者
1 | git deinit <path> |
指向完毕后还要删除.gitmodules的对应信息,并push相关修改到远程仓库同步
在主项目中提交子项目代码
在子项目目录修改代码按照普通的git工作流程后,回到主项目工作
指向git status
会发现有一条修改记录
1 | On branch master |
在主项目执行git submodule update
后, 子仓库就更新到之前旧的版本了!但是无需担心,子项目push过了,远程仓库的代码不会丢失。
这时到git的网页上看主项目的仓库的目录,子目录显示为<path> @ 9397017
,对比子仓库的提交记录,发现后面的多出的字符对应的是子仓库的某条提交记录的commitId
。远程仓库的commitId
还停留在子项目的上一版本。
也就是说,子仓库提交代码后还需要将新的commitId
同步到主项目中去。否则,主项目永远无法获取最新的子项目的最新修改。
按如下步骤同步子项目的commitId
,再到网页上就可以看到子项目的commitId
更新了。 也不会出现子项目代码无法更新的问题了。
1 | git add -u |
将git仓库中的子目录submodule化
除了在项目中新增子module的情况。
小项目在开发的过程中规模也会越来越大,团队扩大,需要将原项目拆分成小项目将一些功能交由专门的人员去维护。
可以为每个子项目采取如下的步骤拆分项目
最好为每个目拆分
克隆原项目
1 | git clone https://gitee.com/XXX/XXX.git path |
进入项目目录执行
1 | git remote rm origin |
拆分子项目
比如原项目中有个子目录下Test的内容需要独立成一个子项目,执行
1 | git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter Test -- --all |
执行完后会发现原项目录下的内容被替换为Test的内容,并且查看日志可以看到当前项目保留了和项目Test修改相关的提交记录
清理残留内容
执行如下命令,清理一些残留的内容,减少仓库体积
1 | git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d |
将子项目push到远程仓库
为子项目创建远程仓库后,执行
1 | git remote add origin https://github.com/XXX/Test.git |
将原项目的内容替换为子module
该操作在原项目的本地仓库中操作,操作前确保需要提交的内容已全部提交
1 | # 删除原项目中的子module文件 |