首页 > 其他分享 >浅析Git Subtree的原理与实际应用:git subtree是什么、子仓库与仓库共用、共用代码需求常规处理方式及为什么使用git subtree以及如何使用Git Subtree在多个Git项目

浅析Git Subtree的原理与实际应用:git subtree是什么、子仓库与仓库共用、共用代码需求常规处理方式及为什么使用git subtree以及如何使用Git Subtree在多个Git项目

时间:2023-02-01 21:57:44浏览次数:43  
标签:npm git 项目 Subtree subtree Git test

一、为什么需要使用Git Subtree

  关于子仓库或者说是仓库共用,git官方推荐的工具是git subtree。

  在实际的项目开发过程中,公共的代码或者模块是必定会出现的,为了不重复写相同的代码;普遍的做法就是将其抽取成一个公共模块,这个模块由不同的使用者引用。

  作为Java工程师,可能会选择将这一部分打包封装成一个jar,并且将其推送到Maven的私有仓库,各个使用者将其添加到pom文件即可;作为前端工程师,可能会选择将这一部分打包封装成一个自定义plugin,将其推送至npm的私有仓库,各个使用者去安装即可。

  但是有没有更好的方式呢?因为使用这种方式,对使用者来说,并不是透明的,当前可能已经更新版本了,但是我作为使用者并不知道当前已经更新了,知道更新了可能也不知道最新版本是多少,我还得通过咨询模块开发人员或者说到私有仓库去查看才能知道,那有没有更好的方式呢?

  接下来,就一起探讨一种更好的管理方式:git subtree。

二、共用代码的需求及处理方式

1、需求背景

  项目A与项目B存在公用模块,在项目A中修改Bug或增加新功能需要同步到项目B中,由于存在区别所以还不能完全copy

2、需求分析

(1)公用代码迁移出去独立的 git 仓库,供其他项目共享代码

(2)公用代码原本是什么样,抽取后也是什么样

(3)公用代码库是可以在不同项目间双向同步的而不是单向同步

(4)保留公用代码库的历史提交记录与双向同步记录

双向同步的例子:A项目中依赖了子项目B,最方便的方式自然是直接在A项目里改B子项目对应的目录里的代码,然后测试通过后,直接提交代码,这个更改也提交到B子项目的 Git仓库里。同时子项目B也可以单独提交到 Git 仓库,再在A项目里把子项目B的代码update。

3、现有方案

(1)Git Submodule:这是Git官方以前的推荐方案

(2)Git Subtree:从 Git 1.5.2 开始,Git 新增并推荐使用这个功能来管理子项目

(3)npm:node package manager,实际上不仅仅是 node 的包管理工具

(4)composer:暂且认为他是php版npm

  虽然 npm,composer,maven 等更侧重于包的依赖管理,以上几个方案都是能够做到在不同项目中同步同一块代码的,但没法双向同步,更适用于子项目代码比较稳定的情形

  Git Submodule 和 Git Subtree 都是官方支持的功能,不具有依赖管理的功能,但能满足我们的要求。Git Subtree相对来说会更好一些 。git v1.5.2以后建议使用git subtree

4、Git Subtree 好在哪里

  用一句话来描述 Git Subtree 的优势就是:

经由 Git Subtree 来维护的子项目代码,对于父项目来说是透明的,所有的开发人员看到的就是一个普通的目录,原来怎么做现在依旧那么做,只需要维护这个 Subtree 的人在合适的时候去做同步代码的操作。

  它是怎么做到的呢?后面会通过实操记录简单说下原理。

三、什么是git subtree?有啥优势?

1、git subtree可以将一个仓库作为仓库的子仓库

2、各个仓库之前的版本管理是相对独立的

3、对于使用者来说,是透明的,可能使用者根本都不知道有子仓库的存在

4、主子仓库的分支同步,即你切换主项目分支的时候,关联的子仓库也会同步切换

四、什么时候需要Subtree

1、当多个项目共用同一模块代码,而且这块代码跟着项目在快速更新的时候

2、把一部分代码迁移出去独立为一个新的 git 仓库,但又希望能够保留这部分代码的历史提交记录

五、Git Subtree的原理与实际应用

  首先,你需要2个主项目,我利用之前的demo项目、demo2项目,还要有一个被多个项目共用的subtree项目。我们通过简要讲解使用Subtree来同步代码的过程来解释Subtree的原理

1、初始化子项目subtree

  通过我之前的demo项目做下示例

cd demo项目的路径  
git subtree add --prefix=用来放subtree项目的相对路径 subtree项目git地址 xxx分支
PS D:\demo\vue-button-test> git subtree add --prefix=/subtree https://gitee.com/***/npm_test.git master
git fetch https://gitee.com/goloving/npm_test.git master
From https://gitee.com/goloving/npm_test
 * branch            master     -> FETCH_HEAD
error: Invalid path 'C:/Program Files/Git/subtree/README.md'
error: Invalid path 'C:/Program Files/Git/subtree/index.js'
error: Invalid path 'C:/Program Files/Git/subtree/package.json'
error: Invalid path 'C:/Program Files/Git/subtree/plugins/lib/button.vue'
fatal: C:/Program Files/Git/subtree: 'C:/Program Files/Git/subtree' is outside repository
PS D:\demo\vue-button-test> git subtree add --prefix=subtree https://gitee.com/goloving/npm_test.git master
prefix 'subtree' already exists.
PS D:\demo\vue-button-test> git subtree add --prefix=subtree https://gitee.com/goloving/npm_test.git master
git fetch https://gitee.com/goloving/npm_test.git master
From https://gitee.com/goloving/npm_test
 * branch            master     -> FETCH_HEAD
Added dir 'subtree'
PS D:\demo\vue-button-test>

  遇到3个报错:

(1)Working tree has modifications. Cannot add. 实际上工作树没有更改,解决:关闭终端,重新开启终端即可

(2)--prefix=/subtree 应该是相对路径,不是绝对路径,所以写 /subtree 匹配到 C:/Program Files/Git/ 去了

(3)--prefix=subtree 刚开始以为必须新建这个目录,发现不是的,新建会报错,删除即可

  这样的命令,把subtree即npm_test项目的代码下载到--prefix所指定的subtree目录中,并在demo项目里自动产生一个commit(就是把npm_test目录的内容提交到demo项目里)

  我们再用一个demo2项目做同样的操作

2、像往常一样更新代码

  大家在demo项目里各种提交commit,其中有些commit会涉及到subtree目录的更改,正如前面提到的,这是没任何关系的,大家也不会感受到有任何不一样。

  比如我们在 npm-test 项目里button按钮后随便加个文字:subtree,看下图 demo 项目生效了

  然后我们把更改的所有内容 git 提交到 demo 项目仓库,我们可以看到下面全部的 commit 记录

 

3、提交更改到子项目的Git服务器

  关键的地方来了: 当维护这个demo项目 subtree 的人希望把最近这段时间对demo项目subtree目录的更改提交到subtree对应的npm_test项目的 Git 服务器上时,他执行一段类似于这样的命令:

cd demo项目的路径  
git subtree push --prefix=用来放subtree项目的相对路径 subtree项目git地址 xxx分支
PS D:\demo\vue-button-test> git subtree push --prefix=subtree https://gitee.com/***/npm_test.git master
git push using:  https://gitee.com/goloving/npm_test.git master
Counting objects: 5, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (5/5), 384 bytes | 384.00 KiB/s, done.
Total 5 (delta 2), reused 0 (delta 0)
remote: Powered by GITEE.COM [GNK-6.3]
To https://gitee.com/goloving/npm_test.git
   adbf133..bbe8c7b  bbe8c7b22181acc371c7118f6392fafa9448ce4f -> master
PS D:\demo\vue-button-test>

  Git 会遍历所有的commit,从中找出针对subtree目录的更改,然后把这些更改记录提交到subtree对应的npm_test项目的Git服务器上

  然后我们就可以看到 npm_test 项目上多个对button更改的记录

4、更新子项目新的代码到父项目

  现在subtree npm_test项目有新代码了,demo2项目也想使用这些新代码,维护demo2项目这个Subtree的人只要执行

cd demo2项目路径
git subtree pull --prefix=subtree项目的路径 subtree项目git地址 xxx分支
PS D:\其他\big-data-view1>  git subtree pull --prefix=subtree https://gitee.com/goloving/npm_test.git master
Working tree has modifications.  Cannot add.
PS D:\其他\big-data-view1>  git subtree pull --prefix=subtree https://gitee.com/goloving/npm_test.git master
remote: Enumerating objects: 9, done.
remote: Counting objects: 100% (9/9), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 5 (delta 2), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (5/5), done.
From https://gitee.com/goloving/npm_test
 * branch            master     -> FETCH_HEAD
Merge made by the 'recursive' strategy.
 subtree/plugins/lib/button.vue | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
PS D:\其他\big-data-view1>

  当有未提交记录时会报这个错误:Working tree has modifications. Cannot add. 解决:将未提交记录全部提交即可

  接下来我们就可以看到 demo2 项目里的 button 按钮就更新为最新的了

  这样就可以将demo2项目里subtree目录里的内容更新为npm_test项目xxx分支的最新代码了。

标签:npm,git,项目,Subtree,subtree,Git,test
From: https://www.cnblogs.com/goloving/p/16678440.html

相关文章

  • 解决git clone下载慢的问题
    修改hosts文件文件位置:Windows:C:\Windows\System32\drivers\etc\hostsLinux:sudogedit/etc/hosts添加以下两行内容:151.101.185.194github.global-ssl.fastly.net192.30.......
  • github - 批量删除仓库存储
    github-批量删除仓库存储github是不提供批量删除的,网上一堆写脚本的形式,让自动去一个一个删除,这里有个更好的办法,一位外国开发者将这个批量删除的功能做成了网站:​​https......
  • Git恢复删除的文件,一行命令就可以啦~
    情况一:删除或者修改了某个文件,但是没有add#单个gitcheckoutfilename#多个gitcheckout.情况二:删除或者修改了某个文件,已经add,但是没有commit#单个gitchec......
  • github与jenkins相结合实现push代码后自动部署
    首先在settings里面设置  jenkins-token记得设置勾选  至此github设置完成jenkins  credentials:选择私钥复制进去,github上放置公钥  将之前的gith......
  • git基础
    查看当前项目的用户名和邮箱地址gitconfiguser.namegitconfiguser.email修改当前项目的用户名和邮箱地址gitconfiguser.name"username"gitconfiguser.......
  • 如何将本地的一个文件、文件夹放到gitee上
    第一步:创建一个git仓库第二步:打开安装的gitbash第三步:cd到要上传的目录下,初始化gitgitinit会在目录下创建一个.git的隐藏文件夹第四步:将文件添加到暂存区里g......
  • Git 客户端基本使用及新手常见问题
    Git作为一个版本管理工具,在企业中的应用越来越普遍。作为一个测试工程师,不可避免会需要接触到Git的相关操作,以下整理Git客户端的常见操作,以及应用中新手常碰到的一些问题。......
  • Git入门图文教程(1.5W字40图)
    01、认识一下Git!—简介Git是当前最先进、最主流的分布式版本控制系统,免费、开源!核心能力就是版本控制。再具体一点,就是面向代码文件的版本控制,代码的任何修改历史都会被......
  • git项目忽略文件
    #Eclipse.project.classpath.settings/#Maventarget/dependency-reduced-pom.xmlpom.xml.versionsBackup.factorypath#Gradle.gradle/build/#IDEA#id......
  • 从零开始配置vim(31)——git 配置
    很抱歉又拖更了这么久了,在这个新公司我想快速度过试用期,所以大部分的精力主要花在日常工作上面。但是这个系列还是得更新下去,平时只能抽有限的业余时间来准备。这就导致我......