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

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.mzph.cn/diannao/13241.shtml

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

相关文章

C#实现各种Hash计算

C#实现各种Hash计算 文章目录 C#实现各种Hash计算涉及框架及库目前支持可计算的类型核心代码完整可运行代码 BCrypt总结 涉及框架及库 自己在NuGet管理器里面安装即可 BouncyCastle.Cryptography:是加密算法和协议的.NET实现。 目前支持可计算的类型 BLAKE2B_16…

如何在Idea离线情况下安装vue.js插件

亲践有效,步骤如下: 1. 互联网环境登陆vue.js官网(Vue.js - IntelliJ IDEs Plugin | Marketplace)。 2. 然后先确定你的IDEA的版本:在你IDEA的安装文件中找到product-info.json,里面的buildNumber记录着你IDEA的精确版本号,根据…

roscore启动报错的解决方法【将环境变量配置于最后】

今天在启动rviz时发生一个很奇怪的报错: rviz: error while loading shared libraries: librviz.so: cannot open shared object file: No such file or directory 我感觉很纳闷!再试着启动一下roscore,发现如下报错: [rosout-1…

Python爬虫从入门到精通:一篇涵盖所有细节的高质量教程

目录 第一部分:Python爬虫基础 1.1 爬虫原理 1.2 Python爬虫常用库 1.3 爬虫实战案例 1.4 注意事项 第二部分:爬虫进阶技巧 2.1 处理动态加载的内容 2.2 登录认证 2.3 分布式爬取 2.4 反爬虫策略 第三部分:爬虫实战项目 3.1 豆瓣…

【C语言】指针(二)

目录 一、传值调用和传址调用 二、数组名的理解 三、通过指针访问数组 四、一维数组传参的本质 五、指针数组 六、指针数组模拟实现二维数组 一、传值调用和传址调用 指针可以用在哪里呢&#xff1f;我们看下面一段代码&#xff1a; #include <stdio.h>void Swap(i…

基于Spring封装一个websocket工具类使用事件发布进行解耦和管理

最近工作中&#xff0c;需要将原先的Http请求换成WebSocket&#xff0c;故此需要使用到WebSocket与前端交互。故此这边需要研究一下WebSocket到底有何优点和不可替代性&#xff1a; WebSocket优点&#xff1a; WebSocket 协议提供了一种在客户端和服务器之间进行全双工通信的…

异地组网群晖不能访问怎么办?

在日常使用群晖网络储存设备时&#xff0c;我们常常会遇到无法访问的情况&#xff0c;特别是在异地组网时。这个问题很常见&#xff0c;但也很让人困扰。本文将针对异地组网群晖无法访问的问题进行详细解答和分析。 异地组网的问题 在异地组网中&#xff0c;群晖设备无法访问的…

Unity | Spine动画动态加载

一、准备工作 Spine插件及基本知识可查看这篇文章&#xff1a;Unity | Spine动画记录-CSDN博客 二、Spine资源动态加载 1.官方说明 官方文档指出不建议这种操作。但spine-unity API允许在运行时从SkeletonDataAsset或甚至直接从三个导出的资产实例化SkeletonAnimation和Skel…

HNU-算法设计与分析-作业3

第三次作业【动态规划】 文章目录 第三次作业【动态规划】<1>算法实现题 3-1 独立任务最优解问题<2>算法实现题 3-4 数字三角形问题<3>算法实现题 3-8 最小m段和问题<4>算法实现题 3-25 m处理器问题 <1>算法实现题 3-1 独立任务最优解问题 ▲问…

Linux(七) 动静态库

目录 一、动静态库的概念 二、静态库的打包与使用 2.1 静态库的打包 2.2 静态库的使用 三、动态库的打包与使用 3.1 动态库的打包 3.2 动态库的使用 3.3 运行动态库的四种方法 四、总makefile 一、动静态库的概念 静态库&#xff1a; Linux下&#xff0c;以.a为后缀的…

Python专题:十五、JSON数据格式

Python的数据处理&#xff1a;JOSN 计算机的主要工作&#xff1a;处理数据 最容易处理的数据就是结构化数据 非结构化数据&#xff1a;视频&#xff0c;文件等 近些年的大数据、数据挖掘就是对互联网中的各种非结构化的数据的分析和处理 半结构化数据 明确的结构属性&…

陪诊服务运用预约小程序的效果是什么

在中高型城市里&#xff0c;陪诊师近些年也很有热度&#xff0c;已经衍生成为一个新的小众行业&#xff0c;不同医院/不同科目等其它情况针对不同群体往往很难完善&#xff0c;比如部分老年人腿脚不便、不认识字、外地语言难以沟通等&#xff0c;陪诊师的作用就尤为凸显. 对相…

[Bootloader][uboot]code总结

文章目录 1、U_BOOT_DRIVER2、DM框架dm_scan_platdatadm_extended_scan_fdt 1、U_BOOT_DRIVER 使用这个宏可以定义一个驱动实例&#xff0c;宏定义是 其中使用的struct driver结构体 使用的ll_entry_declare宏定义是 归结为 2、DM框架 1、 DM框架 DM模型抽象出了以下四个…

16.投影矩阵,最小二乘

文章目录 1. 投影矩阵1.1 投影矩阵P1.2 投影向量 1. 投影矩阵 1.1 投影矩阵P 根据上节知识&#xff0c;我们知道当我们在解 A X b AXb AXb的时候&#xff0c;发现当向量b不在矩阵A的列空间的时候&#xff0c;我们希望的是通过投影&#xff0c;将向量b投影到矩阵A的列空间中&…

ModuleNotFoundError: No module named ‘sklearn‘

ModuleNotFoundError: No module named sklearn 解决办法&#xff1a; pip install scikit-learn

7B2 PRO主题5.4.2免授权直接安装

B2 PRO 5.4.2 最新免授权版不再需要改hosts&#xff0c;直接在wordpress上传安装即可

Vue的学习 —— <网络请求库Axios>

目录 前言 正文 一、Axios基本概念 二、安装Axios 三、Axios使用方法 四、向服务器发送请求 前言 在之前的开发案例中&#xff0c;我们通常直接在组件中定义数据。但在实际的项目开发中&#xff0c;我们需要从服务器获取数据。当其他用户希望访问我们自己编写的网页时&a…

定档 11.2-3,COSCon'24 第九届中国开源年会暨开源社十周年嘉年华正式启动!

中国开源年会 COSCon 是业界最具影响力的开源盛会之一&#xff0c;由开源社在2015年首次发起&#xff0c;今年将举办第九届。 以其独特定位及日益增加的影响力&#xff0c;COSCon 吸引了越来越多的国内外企业、高校、开源组织/社区的大力支持。与一般企业、IT 媒体、行业协会举…

网络安全快速入门(十三)linux及vmware软件的网络配置

13.1 前言 在通过我们前面的了解&#xff0c;我们现在已经对Linux的基础知识有了大致的了解&#xff0c;今天我们来大概讲一下关于linux系统及vmware的网络配置问题&#xff0c;在这之前&#xff0c;我们需要对网络有一个大概的认识和了解&#xff0c;话不多说&#xff0c;我们…

HNU-算法设计与分析-作业5

第五次作业【回溯算法】 文章目录 第五次作业【回溯算法】<1> 算法分析题5-3 回溯法重写0-1背包<2> 算法分析题5-5 旅行商问题&#xff08;剪枝&#xff09;<3> 算法实现题5-2 最小长度电路板排列问题<4> 算法实现题5-7 n色方柱问题<5> 算法实现…