当前位置:   article > 正文

git subtree教程

git subtree

背景

公司要做一个服务平台,有12个领域,每个领域为一个微服务,现在前端项目暂时拆分为三个,分别为SEO,content和forward,三个项目(以后会拆分更多的项目)的组件、插件、工具、状态管理为同一套。现状复制三份一个项目放一份,这样的弊端是一个公共组件修改要同时维护三份,另外不同项目新增不同的组件,随着项目的增多组件的同步、维护成本会越来越大

需求分析

  • (组件、插件、工具)、状态管理等公用代码迁移出去分别建立front-common和front-store(nuxt对vuex进行了封装,为了尽量不改动原目录结构)两个git 仓库,供其他项目共享代码
  • 公用代码原本是什么样,抽取后也是什么样
  • 公用代码库是可以在不同项目间双向同步的而不是单向同步
  • 保留公用代码库的历史提交记录与双向同步记录

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

现有方案


  • Git Submodule:这是Git官方以前的推荐方案
  • Git Subtree:从 Git 1.5.2 开始,Git 新增并推荐使用这个功能来管理子项目
  • npm:node package manager,实际上不仅仅是 node 的包管理工具
  • composer:暂且认为他是php版npm

虽然 npm,composer,maven 等更侧重于包的依赖管理,以上几个方案都是能够做到在不同项目中同步同一块代码的,但没法双向同步,更适用于子项目代码比较稳定的情形。Git Submodule 和 Git Subtree 都是官方支持的功能,不具有依赖管理的功能,但能满足我们的要求。Git Subtree相对来说会更好一些 。

submodule 与 subtree对比

  • git submodule
    • 允许其他的仓库指定以一个commit嵌入仓库的子目录
    • 仓库 clone下来需要 initupdate
    • 会产 .gitmodule 文件记录 submodule 版本信息
    • git submodule 删除起来比较费劲
  • git subtree
    • 避免以上问题
    • 管理和更新流程比较方便
    • git subtree合并子仓库到项目中的子目录。不用像submodule那样每次子项目修改了后要initupdate 。万一哪次没update就直接add ..gitmodulecommit上去就悲剧了
    • git v1.5.2以后建议使用git subtree

拆分已有项目

需要从现有项目中抽取公共模块单独进行git管理首先进行技术预演(展示网址为私有项目,自行替换自己的git仓库地址)
假设原项目test-sub-tree下web目录抽取项目store

  1. 进入项目目录:cd test-sub-tree

ps:直接使用git subtree add 的命令会出现 prefix ‘***’ already exists. 这样的错误提示,这是因为对应的目录已经存在,
不能直接添加,需要把对应的目录剥离开然后再加入subtree

2.剥离出store
git subtree split -P <store项目的相对路径> -b <临时branch>


Git 会遍历所有的commit,分离出store相关的commit,并存入front-store分支中

3. 创建子repo

在git远程创建front-store项目

退出项目目录,在原项目front同级目录创建文件夹,进入front-store目录,把这个目录变成Git可以管理的仓库:
cd …/

mkdir front-store

cd front-store

git init

拉取test-sub-tree项目front-store分支

git pull <test-sub-tree项目的路径> <临时branch>

如果直接用git clone <git地址>来拉取子项目并生成文件夹(我的common项目使用这种方法),执行上述命令
可能会报fatal: refusing to merge unrelated histories错误。

解决办法使用命令: git pull <test-sub-tree项目的路径> <临时branch> --allow-unrelated-histories

关联front-store远程仓库,推送代码到远程
git remote add origin <front-store项目的git仓库>
git push origin -u master

4. 清理数据
cd test-sub-tree项目的路径
git rm -rf <test-sub-tree项目的store相对路径>


git commit -m ‘移除store模块’ # 提交删除申请


git branch -D <临时branch> # 删除临时分支front-store

5. 添加subtree
git subtree add -P <store项目的相对路径> <store项目git地址> <分支> --squash
git push

解释:–squash意思是把subtree的改动合并成一次commit,这样就不用拉取子项目完整的历史记录。-P等于–prefix,之后的=等号可以用空格。

执行完第3步时,对应的目录已经剥离出来形成独立的项目了。第3,4步主要是把当前项目的对应的文件给删除,重新在test-sub-tree项目建立Subtree

项目间双向同步

test-sub-tree项目和front-store正常我们可以进行正常的日常git提交和修改维护

git add .

git commit -m “xxx文件修改”

git pull

git push

两个项目的代码要进行双向同步要执行下面的操作:


1. test-sub-tree项目修改store文件夹下的文件提交更改到front-store子项目
场景test-sub-tree项目删除store文件夹下supply_item文件

现在通过命令:

git subtree push -P <front-store项目的相对路径> <front-store项目git地址> <分支>

将“删除supply_item文件”这个操作同步到front-store子项目的仓库

进入front-store子项目文件夹,拉取远程仓库代码,会看到front-store文件夹下supply_item文件被删除

Git 会遍历步骤2中所有的commit,从中找出针对S目录的更改,然后把这些更改记录提交到S项目的Git服务器上,并保留步骤2中的相关S的提交记录到S仓库中

4. front-store子项目修改提交同步到test-sub-tree项目store文件夹下

场景front-store项目新增supply_item文件

现在通过命令:

git subtree pull --prefix=<front-store项目的相对路径> <front-store项目git地址> <分支> --squash

front-store子项目的“新增supply_item文件”这个操作同步(拉取)到test-sub-tree项目

用git push将front-store子项目修改推送到test-sub-tree项目远程仓库

Tips:相对路径区别大小写

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/寸_铁/article/detail/861260
推荐阅读
  

闽ICP备14008679号