• git submodule 子模块的基本使用


    常用命令

    命令说明
    git submodule add <本地路径>添加子模块
    git submodule update --init --recursive添加子模块后,同步子模块内容
    git clone --recurse-submodules克隆带有子模块的项目
    git submodule init初始化子模块
    git submodule update更新子模块
    git submodule sync --recursive子模块地址变更
    git submodule deinit 删除子模块

    背景

    浏览开源库的时候经常会看到如下子模块的引用情况。
    请添加图片描述

    子模块通常是项目比较复杂,需要对项目进行拆分,而项目又有引用关系时会使用。通常拆分项目后,我只需要关注自己的项目更改,不需要关注引用的项目都做了哪些更改。

    通常这样拆分后,项目就不会在一个 git 仓库中,这时用 submodule 来管理代码仓库会清晰方便许多。

    基本使用

    添加子模块

    git submodule add <本地路径>,例:

    git submodule add https://github.com/grassto/example.git example
    
    • 1

    执行完毕后,发现仓库目录下多了个 example 目录,但是里面没有任何文件,此时需要再执行:

    git submodule update --init --recursive
    
    • 1

    这时会看到仓库有如下变化:

    可以看到 .gitmodules 中有如下内容

    [submodule "example"]
    	path = example
    	url = https://github.com/grassto/example.git
    
    • 1
    • 2
    • 3

    另外,.git/config 中会多出一块有关子模块的信息

    [submodule "example"]
    	active = true
    	url = https://github.com/grassto/example.git
    
    • 1
    • 2
    • 3

    同时在 .git/mudules 目录下会多出 .git/mudules/example 目录。

    克隆带有子模块的项目

    直接 clone 只能拉取主项目的代码,需要多执行下 submodule 相关的命令,如下两种方式:

    git clone https://github.com/grassto/example.git --recurse-submodules
    
    • 1

    先克隆,再初始化子模块拉取

    git clone
    git submodule init
    git submodule update
    
    • 1
    • 2
    • 3

    更新子模块

    git submodule update 
    git submodule update --remote
    
    • 1
    • 2

    不添加 --remote 参数,只更新子模块到该仓库使用的最新版本,例:

    子模块一直在自己开发,更新了 1.0, 1.1, 1.2 版本,但是这时候我的主仓库只使用了 1.0 版本,使用 git submodule update 更新后,发现只能更新到 1.0 版本。

    添加了 --remote 参数,则直接更新到子模块仓库的最新版本。

    简单理解就是主仓库使用的就是特定版本的子模块仓库,若要更新,需要主仓库主动进行更新再提交。

    子模块地址变动

    git submodule sync --recursive
    
    • 1

    若子模块的 url 发生了改变,这时执行 git submodule update 会失败,可以使用 sync 来同步。

    这个我没用过,官网上看到的,这里提一下。

    删除子模块

    git submodule deinit example
    git rm example
    git commit -m "delete submodule example"
    
    • 1
    • 2
    • 3

    推荐使用上面这种方式,当然也可以手动删除:

    • 删除本地子模块目录
    git rm --cached example
    rm -rf example
    
    • 1
    • 2
    • 删除 .gitmodules 子模块信息
    [submodule "example"]
    	path = example
    	https://github.com/grassto/example.git
    
    • 1
    • 2
    • 3
    • 删除 .git/config 文件中的子模块内容
    [submodule "example"]
    	active = true
    	https://github.com/grassto/example.git
    
    • 1
    • 2
    • 3
    • 删除 .git 文件夹中的相关子模块文件
    rm -rf .git/modules/example
    
    • 1

    总结

    • 使用了 submodule 后,若不主动更新,项目会一直使用固定版本的 submodule 模块,需手动更新(git submodule update --remote)。
    • 若是在 go 或者其他有包管理的项目中,建议还是使用开发语言工具去做这种类似的第三方包管理会比较方便。

    其他

    作为一个 go 开发,我还是提议使用 go module 来做这种包管理,这里提一下我使用 submodule 的原因:

    现在用到了一个包引用的是本地的,使用了 replace 特性,在做 gitlab CI 的时候,需要同步代码仓库,感觉不方便,顾使用了 git submodule 将代码作为子模块。这样就可以使用 gitlabGIT_SUBMODULE_STRATEGY: recursive 特性。

    如果你也是个 go 开发人员,这里不建议这么用,因为 go module 是可以引用私有库的,我这样用是有历史原因的。

    我需要引用的库的 go.mod 如下,modulenameexample 而不是 github.com/example

    module example
    
    go 1.18
    
    require ......
    
    • 1
    • 2
    • 3
    • 4
    • 5

    使用该模块的时候都是将其拉到本地,然后 replace

    module work
    
    go 1.18
    
    replace example => ./example
    
    • 1
    • 2
    • 3
    • 4
    • 5

    参考

  • 相关阅读:
    登录认证方式汇总,例如ThreadLocal+拦截器+Redis、JWT
    拼多多快捷回复语
    Lab 1: Unix utilities汇总
    Pandas-04(缺失数据、分组、合并连接、级联)
    Vue模板语法(下)
    Hive企业级调优
    Ubuntu18.04 velodyne 运行loam_velodyne
    Linux学习之进程三
    什么是RPA?
    .NET 6 基于IDistributedCache实现Redis与MemoryCache的缓存帮助类
  • 原文地址:https://blog.csdn.net/DisMisPres/article/details/132604665