美文网首页
git submodule 实践及总结

git submodule 实践及总结

作者: Super超人 | 来源:发表于2019-10-17 18:08 被阅读0次

    合作开发,不得不使用git来进行项目管理,下面来记录下关于git的踩坑记录。

    子模块概念

    对于一些比较大的工程,为了便模块复用,常常需要抽取子项目,分布式管理项目依赖,会用到子模块(git submodule)。

    子模块跟父工程之间是两个独立的git仓库,只是父工程存储了它依赖的子仓库的版本号信息而已,信息提交相互独立。

    子模块创建

    # 在主工程仓库中添加子依赖子模块
    $ git submodule add <远程子模块仓库地址> <相对于项目的本地路径>
    

    下面模拟添加,执行完添加之后会返现本地多了一个.gitmodules隐藏文件。

    $ git submodule add https://github.com/xxx/module.git module
    $ cat .gitmodules
    [submodule "module"]
        path = module
        url = https://github.com/xxx/module.git
    

    查看.gitmodules文件发现其指定了一个依赖的子模块,path指明在主仓库的位置,url指明子模块仓库的远程地址。
    并且在主工程仓库的.git/config配置文件中加入了submodule字段

    [submodule "module"]
        url = https://github.com/xxx/module.git
        active = true
    

    clone带有子模块的仓库

    在主工程仓库添加完子模块并push到远端之后,同事需要clone或者pull主工程仓库之后,会发现子模块依赖信息(有.gitmodules文件),但是子模块文件目录下面是空的,这个时候需要手动对子模块信息初始化并更新。

    $ git submodule init
    
    # 执行结果
    Submodule 'module' (https://github.com/xxxx/module.git) registered for path 'module'
    

    这时.git/config配置文件中会包含有依赖的子模块信息,再执行更新,从远程拉取依赖的commit id子模块代码

    git submodule update
    
    # 执行结果
    Cloning into '/.../MainProject/module'...
    Submodule path 'module': checked out 'submodule commit id'
    

    当多层依赖子模块时(子模块里面依赖有子模块),这个时候就比较麻烦了,每次clone下来之后首先要在第一层依赖的子模块的仓库对子模块进行initupdate,之后再进入依赖有子模块的子模块仓库再进行initupdate,以此递归下去,比较麻烦,此时可以使用下面指令一次性完成递归initupdate

    $ git submodule update --init --recursive
    

    也或者直接在clone的时候完成多层依赖的子模块们的initupdate

    $ git clone --recurse-submodules <远程主工程仓库地址>
    

    这样便省去了手动递归执行$ git submodule init$ git submodule update

    注意:不管是使用系统的递归克隆还是手动递归执行的初始化和更新,此时子模块的HEAD都有可能处于游离状态,需要手动切换到对应的分支

    子模块信息更改

    主工程都记录有依赖的子工程的提交版本,查看主工程依赖的commit id

    $ git submodule status
    
    # 结果
    414b65085b41f4270322716df924625fdbcedf7b module (heads/master)
    

    我们可以cd到子工程仓库目录下面,对子工模块代码做一些修改,在commit之前主仓库status会显示module modified content,显示子模块原先提交版本上有脏数据;在commit之后主仓库的status会显示module new commits,依赖的子模块的提交版本号发生变化,在子模块仓库代码提交并更新到远端之后,便可以提交更新依赖的子模块的提交版本号。

    注意:主工程的提交及更新并不会对子模块代码造成影响,只会影响其依赖的子模块提交版本

    如果同事更新了子模块代码,然后更新了父项目中依赖的版本号。你在主仓库执行git pull之后会发现子模块文件有变更,执行git diff会发现如下更改

    $ git diff
    -Subproject commit f88b46fefb73438e2e65c2b7bc7baba8a64ae5d2 #同事新提交的子模块版本
    +Subproject commit c577a495c14159b3693c54af2a0bb9760d748246 #我们原来依赖的子模块的老版本
    

    这时我们如果对父工程仓库代码直接进行提交,便会更改父仓库依赖的子模块版本号,别人更新下来的父仓库还是依赖老的子模块提交版本。虽然后期可以通过更新依赖版本更正过来,但是也会给平时的合作开发带来不必要的麻烦,因此每次对主仓库进行git pull之后,还要执行git submodule update对依赖的子模块代码进行一次更新。
    但是如果子模块里面还依赖有子模块,我们就需要cd到对应的目录下面,一层层调用子模块更新,此时为了方便,我们可以用git submodule update --recursive指令完成多层子模块代码的更新。

    子模块删除

    删除子仓库 -> 删除.gitsubmodule里相关部分 -> 删除.git/config 文件里相关字段 -> 删除子仓库目录。

    $ git rm --cached <本地路径>
    

    如果未按照上述步骤删除,可能残留在.git/modudles文件夹内。

    相关文章

      网友评论

          本文标题:git submodule 实践及总结

          本文链接:https://www.haomeiwen.com/subject/hpdxuctx.html