• git: 使用submodule进行托管


    1. 问题描述:

    假设我们在 root-project 里需要添加3个submodules:A和B是根项目的子模块。 C又是项目A的子模块。

    root-project
          |
          |-- A
          |   |
          |   |-- C
          |
          |-- B

    2. 准备工作

    mkdir repository             // 模拟远程仓库位置
    
    // 模拟远程子模块A&B
    git init --bare repository/submodule_A.git
    git init --bare repository/submodule_B.git
    
    // 初始化子模块A&B用于测试
    mkdir init
    cd init
    git clone ../repository/submodule_A.git
    git clone ../repository/submodule_B.git
    echo "" > submodule_A/"This is submolue A".txt
    echo "" > submodule_B/"This is submolue B".txt
    
    cd submodule_A
    git add .
    git commit -m "init"
    git push
    
    cd submodule_B
    git add .
    git commit -m "init"
    git push
    
    // 模拟工程目录
    git init --bare repository/prj.git
    git clone repository/prj.git prj/myprj        // 指定路径的话会修改*.git原来目录的名称
    cd prj/myprj/
    echo "" > "This is root project".txt

    目录结构:

    .
    |-- init
    |   |-- submodule_A
    |   `-- submodule_B
    |-- prj
    |   `-- myprj
    `-- repository
        |-- prj.git
        |-- submodule_A.git
        `-- submodule_B.git

    3. 使用submodule进行管理

    添加子模块A&B

    // 使用*.git默认的名称你需要先切换到想放置的目录
    git submodule add ../../repository/submodule_A.git/
    
    // 重新命名文件夹,命名“submodule_B” 为 “renamedB”
    git submodule add ../../repository/submodule_B.git/  renamedB

    结果示意:

    $ tree
    .
    |-- This is root project.txt
    |-- renamedB
    |   `-- This is submolue B.txt
    `-- submodule_A
        `-- This is submolue A.txt

    4.  submodule修改提交

    4.1 提交修改

    切换到submodule的路径下,和git的使用方式相同:

    $ cd submodule_A/
    $ echo "" > submodule_A/"modified in A".txt
    $ git add .
    $ git commit -m "modified"

     

    4.2 更新到远程分支

    第1种是直接push:

    $ git push

    试想一下:

    1. 如果你一个工程里有多个submodules,虽然你每次修改子模块时都有commit;

    2. 但是因为prj没有完成,或者子模块还没有修改到可以发布的程度,所以你每次commit 后并不想更新远程分支。

    3. prj工程已经完成,可以push工程里所有的submodule到远程分支了;但是如果一个个路径再打开push,太麻烦。

    这时就可以使用递归的方法:

    // 模拟修改过程
    $ cd submodule_A/
    echo "" > "modified 2 in A".txt
    $ git add .
    $ git commit -m "modified 2"
    
    $ cd ../renamedB/
    echo "" > "modified 2 in B".txt
    $ git add .
    $ git commit -m "modified 2"
    
    // 提交prj修改记录
    $ cd ..
    $ git add .
    $ git commit -m "update now"

    第2种:使用递归push:

    git push --recurse-submodules=check  // 如果子模块没有提交,会直接报错
    
    // or
    git push --recurse-submodules=on-demand  // 如果子模块没有提交,会尝试提交,提交不成功同时会阻止主仓库的推送

    4.  带有submodule仓库的克隆方法

      1. 直接clone的话是没有submodule信息的,只有文件夹。

    mkdir local
    $ git clone ../repository/prj.git cloneDirect
    $ cd cloneDirect/
    $ tree -a -L 2
    .
    |-- .git
    |   |-- HEAD
    |   |-- config
    |   |-- description
    |   |-- hooks
    |   |-- index
    |   |-- info
    |   |-- logs
    |   |-- objects
    |   |-- packed-refs
    |   `-- refs
    |-- .gitmodules
    |-- This is root project.txt
    |-- renamedB
    `-- submodule_A
    
    8 directories, 7 files

      这是因为,父项目的git并不会记录submodule的文件变动,它是按照commit id指定submodule的git header。

       不过可以先对submodule初始化,然后更新,就可以clone到原module的内容。

      

      2. 第二种方式使用递归clone,添加参数 --recursive

      

    在远程修改submodule及本地更新submodule

      1. 远程更新submodule

      

      2. 本地更新submodule

      2.1 直接pull或者更新submodule是无效的,因为远程prj.git并未记录submodule有任何的改动,即远程prj.git不知道也根本不管submodule有没有更新,除非你在prj.git有commit记录。

      

      2.2 在这种情况下仍要更新submodule,就需要直接进入submodule仓库下并切换为需要的分支进行更新。

      

      2.3 这时prj.git 理所当然地发生了变化,根据需要提交变更记录即可。

      

    在本地修改submodule并push后,他处submodule更新流程

      1. 本地A修改submodule并Push

        1.1. 现在本地submodule添加一个新功能:c.md,然后push。

       

        1.2 接着,提交本次prj.git的变更记录:

       

       2. 他处B更新submodule

        2.1 pull后发现submodule发生了改动:

        

        2.2 使用update对submodule进行更新

        

    删除submodule

      1.  git rm moduleA,即可

      

      这样做git的config文件中仍有相关记录,但是不影响使用,如果新clone的话,就不会有相关的记录了。

      如果介意可以手动将该文件的相关行删除。

      

      2. 新clone后,config则无相关记录

      

    echo "" > "This is root project".txt
  • 相关阅读:
    Neo4j图形数据库备份
    Linux中Tomcat 自动设置CATALINA_HOME方法
    VNC viewer 无法打开oracle 11g图形界面方案
    CYPHER 语句(Neo4j)
    Tomcat部署时war和war exploded区别
    java中不能使用小数点(.)来作为分隔符
    做一个完整的Java Web项目需要掌握的技能
    从零讲Java,给你一条清晰地学习道路!该学什么就学什么!
    MYSQL数据库表排序规则不一致导致联表查询,索引不起作用问题
    chrome浏览器的跨域设置——包括版本49前后两种设置
  • 原文地址:https://www.cnblogs.com/qiyuexin/p/9926630.html
Copyright © 2020-2023  润新知