美文网首页
git submodule

git submodule

作者: 老虎爱吃母鸡 | 来源:发表于2017-07-06 00:27 被阅读0次

    目的

    1. 分开管理
    2. 如果是添加公共的库到当前项目中,比起直接复制代码,submodule能追踪上游的更新

    添加submodule

    git submodule add <repository> [<path>]
    

    添加后会多一个.gitmodules文件,文件的内容只是保存submodule的引用信息,包括路径和repo地址

    [submodule "simple-todos"]
        path = simple-todos
        url = git@github.com:GuoQichen/simple-todos.git
    

    添加完后需要在主项目git commit提交新增子项目文件夹以及.gitmodules文件的修改

    在子项目加入到项目的时候,其实做了这样三件事:

    1. 记录引用的子项目仓库,在.git/config
    2. 记录当前项目中子项目的目录位置,在生成的.gitmodules
    3. 记录子项目的commit id

    所以在当前项目push到remote repository的时候,只是更新了引用的commit id,那么在其他人clone项目的时候,就可以获取子项目的commit id,然后在git submodule update的时候获取子项目commit id所表示的commit

    clone带有submodule的项目

    查看子模块的commit id,如果子模块没有被checkout,前面会有-,那么就需要git submodule initgit submodule update

    git submodule
    // result
    b6bf4d6a6cbaaff39e4e4d4f3108d16267354844 simple-todos (heads/master)
    // or
    -b6bf4d6a6cbaaff39e4e4d4f3108d16267354844 simple-todos (heads/master)
    

    clone带有submodule的项目的两种方法:

    1. 第一种
    git clone <repository>
    git submodule init
    git submodule update
    
    1. 第二种
    git clone <repository> --recursive
    

    其实相当于

    git submodule update --init --recursive
    

    注意,在clone之后,cd submodule/,然后git status,你会看到这样的状态

    HEAD detached at b6bf4d6
    nothing to commit, working tree clean
    

    也就是说,现在是detached HEAD,使用git branch就可以查看到

    > * (HEAD detached at b6bf4d6)
    > master
    

    所以需要git checkout master到master分支,然后在master分支上修改

    为什么呢?因为父项目不记录子模块的修改,只记录commit id,所以clone的时候只获取到对应的commit,而不在任何分支上,但是master分支的commit id和HEAD保持一致,所以只要git checkout master,而不需要新建分支

    修改submodule

    注意:只有子项目内容更新,就需要更新父项目引用的子项目的commit id

    其实子项目和父项目只是独立的git项目,所以其他操作和一般git项目一样,在子项目修改,需要

    cd submodule/
    git add .
    git commit - m 'xxx'
    git push
    

    其实普通的git项目一样操作,然后需要在父项目更新引用的子项目commit id,有一种方法:

    1. git submodule update
      但是现在的子模块指向的不是master分支,而是commit id表示的commit,所以还需要
    cd submodule/
    git checkout master
    // todo
    

    为什么这种方法不行呢,其实是个坑!就是你git submodule update之后,你的子项目会恢复到你父项目引用的那个commit,也就是不是最新的commit,此时git status是干净的,就像第一次git clone项目然后git submodule initgit submodule update一样,子项目指向的是父项目引用的那个commit,所以此时把子项目git checkout master之后,再切回到父项目,使用git status,你会发现提示子项目有新的commit,所以还是需要父项目更新引用的子项目的commit id

    1. 在父项目更新引用的子项目commit id
    git commit -m 'update submodule commit id'
    git push
    

    更新submodule

    注意:如果更新submodule的时候有新的commit id产生,需要在父项目产生一个提交,用来更新对子项目commit id的引用
    两种方法:

    1. git submodule foreach git pull
      直接在父项目运行,这样能一次性把所有子项目都更新
    2. 到子项目中去更新
    cd submodule/
    git pull
    

    总结

    子项目一旦产生变动,有新的commit id,父项目必需产生一个提交,更新对子项目commit id的引用

    参考

    Git Submodule使用完整教程
    使用Git Submodule管理子模块
    Git submodule的坑

    相关文章

      网友评论

          本文标题:git submodule

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