进阶 - 子模块

  • 作者:KK

  • 发表日期:2020.06.05


背景

一般项目都不会有子模块,少数就会有,所以大家通常是接触不到这个知识点的,然而某一天你突然发现新到手的项目跑不起来,或者你也有添加子模块的需求,OK看看本文


拉取子模块

这种情况下,就是项目里的某个目录是空的,它其实是引用了另一个 git 项目,那个 git 项目 就是它的子模块。

所以如果你只是clone了一个项目下来跑不起来,那还需要补充运行这么一个命令才能把子模块拉进来:git submodule update --init --recursive

你会看到有一些文章会用这种分解的方式来执行初始化和更新2条命令:

git submodule init
git submodule update

给你的项目添加子模块

比如我们要将https://github.com/gorilla/websocket这个项目添加到我们的项目里作为它的子模块,那就行git submodule add https://github.com/gorilla/websocket.git

  1. 你会发现多了一个websocket目录,它就是以 git 项目的名称来创建的一个目录。

  2. 你还会发现多了一个.gitmodules的文件,它登记了该项目到底有哪些子模块,打开它你可以看到 它里面会有这样的内容:

    [submodule "websocket"]
         path = websocket
         url = https://github.com/gorilla/websocket.git
    
  • *要点:你需要将.gitmodule子模块目录提交代码仓库里,而不需要提交子模块的程序目录文件的时候,就这里的例子来说,我们需要执行以下命令:

    git add .gitmodules websocket git commit -m 添加子模块 .gitmodules websocket git push

    这里虽然将 websocket 这个目录也提交了,但实际上也只是提交了一个子模块目录,而并没有提交里面的文件,你可以浏览远程仓库确认一下 websocket 目录里面,是空的对吧?如果某个浏览工具比较智能,它会在你点击目录时直接帮你跳转到子模块所指向的项目页面,而不再逗留在你原来的项目,于是项目之间就通过 submodule 这个特性连接起来了。


克隆项目的时候就把子模块一起克隆下来(少用)

git clone --recurse-submodules 项目地址,这样就不用再单独执行初始化和更新命令。

其实一般人都不会去背这个参数(可能是因为大家不经常接触 recurse 这个单词),又由于一般项目都不会包含子模块,所以一般人拉项目时都不会打这个参数。

这种操作的实际使用场景多数是用在自动化拉取仓库代码的脚本里面。


更新子模块的代码

子模块作为另一个独立的仓库,维护人员发生修改时,我们这样同步

#进入子模块的项目目录
git fetch   #拉取最新变更信息,但不应用到本地文件
git merge origin/master   #从拉取到的变更信息里,把主分支的变更合并到这个子模块目录