【Git教程】(十八)拆分大项目 — 概述及使用要求,执行过程及其实现,替代解决方案 ~

news2024/11/16 13:53:27

Git教程 · 拆分大项目

  • 1️⃣ 概述
  • 2️⃣ 使用要求
  • 3️⃣ 执行过程及其实现
      • 3.1 拆分模块版本库
      • 3.2 将拆分出的模块作为外部版本库集成
  • 4️⃣ 替代解决方案

在这里插入图片描述

通常软件项目都是由单体小型系统开始的,在开发过程中项目规模和团队人员不断扩大, 将项目模块化会显得越发重要。第一步是将项目内部结构模块化,最终会需要将各个模块独立开发并拥有不同的提交发布周期。

由于 Git 版本库是以整个版本库作为一个整体来发布版本的,所以每个拥有独立发布周期的模块都需要新的Git 版本库。
为 Git 版本库拆分模块过程中的挑战之处在于要尽可能保留原版本库中文件及其版本信息。同时,新的版本库不应该包含本模块不需要的文件,也不需要包含那些没有更改本模块相关文件的提交。

在主版本库中,模块的历史没有被删除,所以原项目中的历史版本已然存在并可以复现。因此,不同模块的历史数据同时存在于拆分前后两个版本库中。
大部分拆分出的模块依然被主项目所需要,应以外部模块的角色集成到主项目中,这种集成关系,在Git 中被称为子模块 (submodule)。

这段工作流演示了如何在Git 中抽取模块,同时实现这样3种目标。

  • 只有该模块所需要的文件被导入到新版本库。
  • 模块文件历史将被保留在新版本库中。
  • 模块可以作为外来模块再次被集成到主项目中。

1️⃣ 概述

接下来这段操作中,我们使用如图上部显示的项目结构为例。这段实例工作流是基于Java 目录结构的,整个项目有3个模块,每个模块中的文件分别置于源代码 (src) 和测试代码 (test) 两个子目录中。换句话说,也就是每个模块包括两个部分。接下来将模块3分化到独立的版本库中。

第一步,删除所有无用的文件,使用 filter branch 命令在原版本库的一个克隆分支上提交即可。接下来,更新新模块版本库的目录结构用以管理模块3。最后,将模块3从原项目中移除,再将新模块版本库作为子模块合入原项目的外部引用目录中,结果如图下部所示。

在这里插入图片描述
新的模块版本库中可以重建文件的修改历史,也就是跟踪记录谁在什么时间做了什么修改,但是不可以完整地重现历史版本。原因是一个模块的文件往往源自另外一些模块。在模块版本库中尝试恢复项目的某一历史版本可能不仅会涉及本模块目录,而是不同目录文件的混杂集合。而且,在过去的版本中本模块可能被用作某些文件的依赖,而这些文件已经不存在了。
在主版本库中,整个项目的旧版本依然可以恢复重现。


2️⃣ 使用要求

  • 项目内部需要模块化时:项目内部需要被分为不同的模块,比如当某一模块需要独立开发和发布版本。
  • 模块文件被分置于不同的目录中时:这时要提取模块的某一历史版本,文件在不同个目录中将需要不同的处理,如果文件十分分散代价将非常大。

3️⃣ 执行过程及其实现

一个模块从项目中被删除并迁移到独立的版本库中,提交历史将被保留下来,无用的文件和提交历史将被删除。独立模块将以外部子模块的形式回到项目中。

需要注意,部分以下命令将彻底改变版本库。虽然 Git 中改变通常可以撤回,但仍应在开始之前确保你的版本库已备份。

> git clone --no-hardlinks --bare projekt.git projekt.backup.git

使用 --no-hardlinks 选项来保证克隆的版本库和源版本库不共享任何文件。


3.1 拆分模块版本库

  • 第1步:克隆主版本库
    作为模块版本库的起点,首先将主版本库克隆一份。

    > git clone --no-hardlinks --bare projekt.git modul3-work.git
    
  • 第2步:删除无用的文件和提交
    接下来,必须删除无用的文件和提交,这是最复杂的一步,也是为了保留模块历史至关重要的一步。
    删除一个版本库中的部分内容可以用 filter-branch 命令。它将针对待修改的提交来创建一次新的提交,通过配置不同的过滤器来改变这次提交的内容。
    以下示例 filter-branch 命令将删除 src/module1 目录下内容。

    > cd module3
    > git filter-branch --force --index-filter
    'git rm -r -cached --ignore-unmatch src/module1'
     --tag-name-filter cat
     --prune-empty -- --all
    

    参数可以这样配置。

    • --index-filter 'git rm -r -cached --ignore-unmatch …': 通过配置这样的参数,可以将文件从提交中移除。rm 命令逐个提交操作。在如上示例中,将作用于src/module1文件目录。 如果待清理的项目没有明显的模块化结构层次,可能需要删除多个文件或多个文件目录。
    • --tag-name-filter cat: 可以为已经存在的或者新建的提交标注标签。
    • --prune-empty: 将删除经过前面的过滤器后不包含任何文件的空提交。
    • --all: 将过滤器适用于整个项目的所有分支。
      在示例的项目中,如此的操作需要依次在 test/module1 、src/module2 和 test/module2 文件目录下执行。
      关于 filter branch 命令每项参数的详细描述,可以参照 Git 帮助。
  • 第3步:删除无用的分支和标签
    不是所有标签和分支在新的模块分支都有意义。例如,那些与模块不相关的文件标签和分支就是无意义的,需要被删除。

    > git tag -d v1.0.1
    > git branch -D v2.0_bf
    
  • 第4步:缩减模块版本库的规模
    Git 为了缩减规模在管理数据中删除无用的文件需要重复克隆一次。

    > git clone --no-hardlinks
    --bare module3-work.git module3.git
    

    这样,过去的模块版本库 module3-work.git 就不再有效,可以删除了。

    > rm -rf modul3-work.git
    
  • 第5步,定制模块版本库文件架构
    到目前为止,新版本库的文件结构和主项目一样,只是删除了无关本模块的文件。调整文件目录结构是通过一般的文件操作完成的,为了这个目的,首先应做一份带有工作空间的克隆。

    > git clone module3.git module3
    

    将源代码目录 src/module3 重命名为 src , 测试代码目录 test/module3 重命名为 test

    > cd module3
    > mv src/module3 module3
    > rmdir src
    > mv module3 src
    > mv test/module3 module3
    > rmdir test
    > mv module3 test
    

    接下来,修改操作通常是借助于commit 命令,再通过 push 上传到干净的版本库中。

    > git add --all
    > git commit -m "Directory structure adapted"
    > git push ,
    

    如果版本库中有多个分支,那文件操作要在各个分支上依次完成。 .
    通常没有必要保留主项目所有的分支。新的版本库有新的分周期,旧分支通常没有意义。

  • 第6步:在主项目中删除已被拆分出来的模块目录
    当拆分出的模块已迁移到新的版本库中,下一步就是让主项目来做拆分后的调整。删除 无用的源代码目src/module3 和测试目录 test/module3。这里的调整主要是在主版本库中的一些普通的文件操作。

    如果项目中有多个分支需要集成这一个改变,那也需要分别进行调整。cherry-pick 命令可以用作将变化调整部署到不同的分支。


3.2 将拆分出的模块作为外部版本库集成

经过前面一系列操作,现在已经拥有两个版本库了,通常原主项目仍需引用拆分后的模块,所以需要集成操作。
集成操作严格依赖于开发平台。例如在 Java Maven项目中,可以将拆分出的模块项目独 立创建编译,并将结果保存在 Maven 项目中,在主项目中将其定义为依赖条件,在创建编译主项目的过程中充 Maven 中获得模块项目。

如果使用 Git 来执行集成操作,那就需要用到子模块 (submodule) 。 有了子模块, 一个Git版本库就可以链接到另外一个 Git版本库了。

在上述示例中,模块3 (module3) 的版本库被链接到了主项目的extern/module3 文件目录下。首先从主项目版本库的一个克隆版开始操作。选定项目的根目录,使用 submodule add 命令加入子模块,该命令有两个参数,第一个是模块版本库的路径或 URL, 第二个参数是在主项目中即将链接的路径。

>git submodule add /global-path-to/module3.git extern/module3

submodule add 命令会在特定的目录下创建一个模块版本库的克隆,这个克隆会在主版本库中作为外部引用。
文件目录 extern/module3 指向外部版本库的最新一次提交 (HEAD) 。
截至目前,子模块只能在工作区中可见,需要只用 commit 命令提交使修改作用于整个版本库。

>git add -all
>git commit -m "Modul3 added"

可以使用 push 命令将添加子模块链接捷径的修改推送到中央版本库。


4️⃣ 替代解决方案

  • 何不采用一个全新的版本库
    有另外一种可以考虑的替换方案是简单地为模块创建一个新版本库。那么,新版本库中就没有原模块的历史记录了,但是原始版本库中仍然有模块的旧版本信息。如果这种缺陷可以被接受,那这种方案在实现上显得最为简单。

  • 为什么不采用 --subdirectory-filter 选项
    使用 filter-branch 命令和 -index-filter 参数可以实现将提交中的文件删除。
    filter-branch 命令的 --subdirectory-filter 参数可以指定将排除某一文件夹之外的文件全部删除,还可以在删除指定的文件夹后改变项目的根目录节点。

    只要模块全部独立存储在一个文件目录下,那么这个命令就可以较方便地用来创建模块版本库。在上文示例中,模块文件被分散在两个目录下,因此不能适用这样的操作。

    即使模块中的文件所属文件目录被迁移或者被改名, subdirectory-filter 仍然可以保留部分历史信息。



温习回顾上一篇(点击跳转)
《【Git教程】(十七)发行版交付 — 概述及使用要求,执行过程及其实现,替代解决方案 ~》

继续阅读下一篇(点击跳转)
《》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1678137.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【保姆级】生成式网络模型基础知识(图像合成/语音合成/GPT)

生成式模型基础知识 初步接触生成任务 生成任务,顾名思义就是要去生成一个东西,比如生成图片/音频/文字等等。 大家接触最多比如chatGPT、stable diffusion、还有一些语音合成相关的东西。 那么问题来了,具体生成步骤是什么样的&#xff…

【Kibana】快速上手Kibana平台(KQL)

文章目录 快速使用Kibana平台常用查询语句KQL基本查询覆合查询模糊查询 目前市面上大部分的公司的日志系统都是使用ELK系统,因此我们进行工作必须得掌握Kibana平台的基本使用,这里主要说明怎么“快速使用Kibana平台”以及记录一些常用的“KQL语言”。 快…

数字化应用标杆 | 又两家成套厂效率翻倍,利用率高达93%以上!

利驰 联能 & 利驰 俊郎 近日,利驰数字科技(苏州)有限公司(简称利驰软件)成功与俊郎电气有限公司(简称俊郎电气)、浙江联能电气有限公司(简称联能电气)成功确立了数字…

Elasticsearch_sql插件安装+使用

一、安装 前提是你先安装好了elasticseach,安装过程在我上一篇博客有说,可以看一下。 在elasticsearch容器启动的情况下,进入到elasticsearch容器,Elasticsearch_sql仓库,比如我的版本是8.11.2,那么我就选…

618值得入手的数码有哪些?数码好物清单推荐|款款实用闭眼冲

每年的618购物节都是消费者们翘首以盼的盛宴,这一天,各大品牌和电商平台都会推出极具吸引力的优惠活动,让消费者们能够以更优惠的价格购买到心仪的数码好物,为了帮助大家在这个购物狂欢节中挑选到真正实用、性价比高的数码产品&am…

javaSE:类和对象

面向对象 java是一种面向对象的编程语言,面向对象就是把能为我们所用的东西直接拿来使用,省去中间过程,比如洗衣服,要完成这一个动作,我们本来需要一个盆,放水,放衣服,换水&#xf…

MATLAB公式推导和导出Latex格式的方法

最近在推机械臂正逆运动学公式,那个旋转矩阵乘起来是真滴多,手算算的脑浆疼。突然想起来MATLAB还有符号计算这个功能,于是翻了翻手册, 找到了这个利用MATLAB帮助计算公式并且直接导出Latex格式的办法。 先定义符号变量&#xff0…

LeetCode2352相等行列对

题目描述 给你一个下标从 0 开始、大小为 n x n 的整数矩阵 grid ,返回满足 Ri 行和 Cj 列相等的行列对 (Ri, Cj) 的数目。如果行和列以相同的顺序包含相同的元素(即相等的数组),则认为二者是相等的。 解析 针对题目给出的数量级…

【源头活水】顶刊解读!IEEE T-PAMI (CCF-A,IF 23.6)2024年46卷第二期

“问渠那得清如许,为有源头活水来”,通过前沿领域知识的学习,从其他研究领域得到启发,对研究问题的本质有更清晰的认识和理解,是自我提高的不竭源泉。为此,我们特别精选论文阅读笔记,开辟“源头…

HarmonyOS NEXT 阅读翻页方式案例

介绍 本示例展示手机阅读时左右翻页,上下翻页,覆盖翻页的功能。 效果图预览 使用说明 进入模块即是左右翻页模式。点击屏幕中间区域弹出上下菜单。点击设置按钮,弹出翻页方式切换按钮,点击可切换翻页方式。左右翻页方式可点击翻…

内存函数:memcpy(拷贝),memmove(拷贝),memcmp(比较),memset(设置)

内存函数 一.memcpy(内存拷贝1)1.函数使用2.模拟实现 二.memmove(内存拷贝2)1.函数使用2.模拟实现 三.memcmp(内存比较)1.函数使用2.模拟实现 四.memset(内存设置)1.函数使用2.模拟实…

【Doris的安装与部署】

1 集群规划和环境准备 Doris作为一款MPP架构的OLAP数据库,可以在绝大多数主流的商用服务器上运行。 1.1 环境要求 一般推荐使用Linux系统,版本要求是CentOS 7.1及以上或者Ubuntu 16.04及以上,这也是目前服务器市场最主流的操作系统。 操作…

算法练习day4

前言 中间个人原因断了很久,现在回来继续。。。。 两两交换链表中的节点 代码随想录 两两交换链表中的节点 24. 两两交换链表中的节点 - 力扣(LeetCode) (用时:0.3小时) 思路 这道题的思路其实很简单…

[数据结构]红黑树的原理及其实现

文章目录 红黑树的特性红黑树的时间复杂度推导:结论红黑树与AVL树比较 红黑树的插入红黑树的节点定义调整策略思考情况2:思考情况3: 代码实现myBTRee.htest.cpp 红黑树的特性 红黑树最常用的平衡二叉搜索树。跟AVL树不同的是,红黑…

OpenAI 推出革命性新模型 GPT-4o:全能AI的新纪元

GPT-4o 模型的推出预示着人工智能领域的又一次飞跃,它将如何改变我们的世界? 在人工智能的快速发展浪潮中,OpenAI 再次站在了技术革新的前沿。2024年5月14日,OpenAI 宣布了其最新旗舰模型 GPT-4o,这不仅是一个简单的版…

GitHub操作

远程库-GitHub GitHub网址 GitHub是全球最大的远程库 1. 创建远程库 2. 远程仓库操作 2.1 创建远程仓库别名 git remote -v 查看当前所有远程库地址别名 git remote add 别名 远程地址 设置远程库地址别名 案例操作 起一个别名会出现两个别名,是因为既可以拉取…

艺人百度百科怎么创建

创建艺人百度百科是一个相对复杂的过程,需要遵循一定的步骤和规则。以下是百科优化网yajje整理的艺人百度百科创建指南: 了解百度百科的创建流程 在创建艺人百度百科页面之前,首先需要了解百度百科的创建流程。可以通过访问百度百科的官方网…

uniapp如何打包预约上门按摩APP

uniapp如何打包预约上门按摩APP? 开发工具:HBuilderX 一、创建移动应用 1、 点击此处微信开放平台 2、点击【管理中心 - 移动应用 - 创建移动应用】填写资料后等待审核 app运行流程图 签名如何获取: 1)先把打包好的app安装在手…

防爆安检系统市场规模保持增长态势 行业将向智能化方向发展

防爆安检系统市场规模保持增长态势 行业将向智能化方向发展 防爆安检系统,是指为了防止爆炸物品及其他危险物品进入特定区域而设置的一套完整的设备系统,细分产品包括金属探测器、生物安全检测设备、爆炸物探测器等。防爆安检系统能够有效检测并识别出潜…

单文件组件,为什么要使用 SFC

介绍 Vue 的单文件组件 (即 *.vue 文件&#xff0c;英文 Single-File Component&#xff0c;简称 SFC) 是一种特殊的文件格式&#xff0c;使我们能够将一个 Vue 组件的模板、逻辑与样式封装在单个文件中。下面是一个单文件组件的示例&#xff1a; <script setup> impor…