git subtree使用说明

  |   0 评论   |   0 浏览

为什么要使用subtree

在实际的项目开发过程中,公共的代码或者模块是必定会出现的,为了不重复写相同的代码;普遍的做法就是将其抽取成一个公共模块,这个模块由不同的使用者引用;作为java工程师,可能会选择将这一部分打包封装成一个jar,并且将其推送到Maven的私有仓库,各个使用者将其添加到pom文件即可;但是有没有更好的方式呢?因为使用这种方式,对使用者来说,并不是透明的,当前可能已经更新版本了,但是我作为使用者并不知道当前已经更新了,知道更新了可能也不知道最新版本是多少,我还得通过咨询模块开发人员或者说到私有仓库去查看才能知道,那有没有更好的方式呢?
接下来,就一起探讨一种更好的管理方式:git subtree,如果说你现在还不知道git是啥或者怎么用?强力建议去学习一下。

什么是git subtree?有啥优势?

  • git subtree可以将一个仓库作为仓库的子仓库
  • 各个仓库之前的版本管理是相对独立的
  • 对于使用者来说,是透明的,可能使用者根本都不知道有子仓库的存在;
  • 主子仓库的分支同步,即你切换主项目分支的时候,关联的子仓库也会同步切换

缺点

  • 需要学习新的操作指令,git subtree有自己的一套指令
  • 指令的复杂度比较高,相比于常规的操作指令,其更加的复杂;
  • 子仓库操作的时候,由于关联了其他仓库,因此指令的响应速度没有单仓库快
  • 子仓库的分支管理比较麻烦

指令列表

git subtree add   --prefix=<prefix> <commit>
git subtree add   --prefix=<prefix> <repository> <ref>
git subtree pull  --prefix=<prefix> <repository> <ref>
git subtree push  --prefix=<prefix> <repository> <ref>
git subtree merge --prefix=<prefix> <commit>
git subtree split --prefix=<prefix> [OPTIONS] [<commit>]

几条指令而已,再复杂也只有这么几条,所以相对于他的优点来说,上面说的缺点也就只是微乎其微了

操作说明


在码云上面创建了三个仓库用于做测试:praent(主仓库), childa、childb(子仓库)

  • 引入子仓库

    git remote add -f <仓库别名> <仓库地址>
    #如 git remote add -f childa https://gitee.com/pengfeilu/subtree-childa.git
    

    这条指令不是git subtree的指令,只是为了方便后续的操作,把仓库引入到当前项目作为一个remote,并且给其取了个别名,后续的操作 childa = https://gitee.com/pengfeilu/subtree-childa.git


  • 添加子仓库
    git subtree add --prefix=<prefix> <repository> <ref>
    #如: git subtree add --prefix=childa childa master --squash
    #等价于: git subtree add --prefix=childa https://gitee.com/pengfeilu/subtree-childa.git master --squash
    
  • 第一个参数 --prefix=modulea
    指明子仓库放在父仓库存放的路径,--prefix可以使用大写的-P简写;这里是放在childa目录,也允许设置多级目录,如childa/a/b/c
  • 第二个参数 modulea
    子远程仓库地址,由于上面一个做了关联,所以这里直接使用的别名,直接使用远端地址也是可以的
  • 第三个参数 master : 添加的子仓库的分支名称,这里使用标签或者commitId也是可以的
  • 第四个参数 --squash: 只将本次操作在主仓库生成一条commit记录,子仓库的历史记录并不会合并进来,可以根据实际情况使用

  • 推送更新到子仓库
    git subtree push  --prefix=<prefix> <repository> <ref>
    #如:git subtree push  --prefix=childa childa master
    #等价于: git subtree push  --prefix=childa https://gitee.com/pengfeilu/subtree-childa.git master
    

    参数说明等价于上面添加的参数


  • 更新子仓库代码
    git subtree pull  --prefix=<prefix> <repository> <ref>
    #如:git subtree pull  --prefix=childa childa master --squash
    #等价于: git subtree pull  --prefix=childa https://gitee.com/pengfeilu/subtree-childa.git master --squash
    

    测试:

    1. 子仓库childa添加文件并上传
    2. 主仓库基于分支获取最新的 childa的提交

  • 对已有的项目目录进行拆分
    以上的操作是我们从一开始就考虑好那一部分是子仓库,从一开始就将子仓库定义好了,这种场景比如在RPC(thrift、grpc等)相关框架自动生成的代码,那么这个子仓库就是用于保存自动生成的那部分代码,而且从一开始就有了,客户端和服务端直接引用就好了;但是业务开发,可能会出现做到一半,发现某一部分可以抽离出来作为一个公共的子模块,那该怎么做呢?

    git subtree split --prefix=<prefix> [OPTIONS] [<commit>]
    

    如当前我的项目下有个文件夹myfile,我需要将其剥离成一个新的子项目childb

    1. 第一步,将myfile目录剥离成一个新的分支
      git subtree split -P myfiles -b childb
    2. 在主项目的同级目录创建一个用于保存这个分支的文件夹
      # 创建文件夹 mkdir ../subtree-childb # 切到对应的文件夹 cd ../subtree-childb/ # 初始化成一个git仓库 git init
    3. 将剥离出来的分支并到当前目录来
      # ../subtree-praent 为主仓库的路径
      # childb 为第一步剥离出来的分支名称
      git pull ../subtree-praent childb
      
      

    4. 将新的仓库关联到远端仓库
      git remote add origin https://gitee.com/pengfeilu/subtree-childb.git
      

    5. 推送到远端代码
      git push -u origin +master
      

    到此!git subtree的常规操作都覆盖了,具体可以在实际使用中去体会!



标题:git subtree使用说明
作者:码霸霸
地址:https://blog.lupf.cn/articles/2019/11/16/1573890420632.html