Monorepo 下 Git 工作流的最佳实践

news2024/10/5 3:20:07

作者:林宜丙

背景

没有哪一种 Git 工作流是银弹,合适的 Git 工作流往往取决于项目的代码规模、协作人数、应用场景等;本次分享先从适合小型 Monorepo 的 Feature branch 工作流开始分享,接着分享适用于中大型 Monorepo 的 Trunk-based 工作流,并给出一些选型标准供同学们参考,希望通过本次分享,大家能找到合适自己 Monorepo 工程的 Git 工作流!

前置知识

我们最熟悉的 Git 工作流莫过于 Git flow, Gilab flow, Github flow,而对于 feature branch 和 trunk-based 比较陌生,那么以上几种 flow 有什么关系呢?

  1. Feature branch 和 Trunk-based 工作流是比较新晋的概念,二者是相对的、互斥的,它们组成一个全集;
  2. Git flow, Gilab flow, Github flow 都属于 feature branch development,它们有一个共同点:都采用『功能驱动式开发』,即:需求是开发的起点,先有需求再有功能分支(feature branch)或者补丁分支(hotfix branch);

适用场景

在 Monorepo 工程中,使用 feature branch development 开发模式时,随着代码库复杂性和团队规模的增长,并行的『长期分支』也会越来越多,这些分支在合入主干时,将会频繁遇到冲突或者不兼容的情况,而手动解决代码冲突往往会引入 Bug。

而 trunk-based development 鼓励开发者可以通过一些小的提交创建『短期分支』,从而大大缓解冲突问题,有助于保持生产版本的流畅。

总的来说,选择一个工作流不仅仅是一系列操作工具的流程,我们往往还需要对它背后的思想买单;下面的表格是两种工作流模式在各个维度的适用情况:

目前大部分业务场景使用的都是 feature branch 的开发模式,如果你的业务是多人开发一个巨型应用(如抖音主站、飞书文档等),应该尝试使用 Trunk based 开发模式,这会提高仓库整体工程质量和管理水平。

展开说说

Feature branch development

什么是 feature branch development?

  • 定义

『功能分支开发模式』的核心思想是所有特性开发都应该在专用的分支,而不是主分支中进行。这种封装使多个开发人员,可以轻松地在不干扰主代码库的情况下处理特定功能。这也意味着主分支永远不会包含损坏的代码,这对于持续集成环境来说是一个巨大的优势。-- Git Feature Branch Workflow | Atlassian Git Tutorial

  • 上线模式

  1. 从 master 分支创建一个功能分支(Feature Branch)
  2. 开发者们在功能分支中完成开发工作
  3. 构建功能分支,并通知 QA 进行验证
  4. 如果发现任何问题
  • 开发者创建一个基于功能分支的修复 MR
  • 经过代码审阅和合并过程将修复 MR 合入功能分支
  • 再重新构建部署,并通知 QA 进行验证
  1. QA 验证通过后,将功能分支发布至线上,然后将其合并入主干后删除

为什么使用 feature branch development?

  • 多功能并 行开发

使多个开发人员可以轻松地在不干扰主代码库的情况下处理特定功能。

  • 保持主分支稳定

主分支永远不会包含损坏的代码,这对于持续集成环境来说是一个巨大的优势。

  • 心智负担低

仅需了解简单的操作即可实践,无需了解 cherry-pick, feature flag 等概念。

Trunk-based development

什么是 trunk-based development?

  • 定义

『基于主干的开发模式』是一种版本控制管理实践,开发者将小而频繁的更新合并到核心『主干』(通常是 master 分支)。

这是 DevOps 团队中的一种常见做法,也是 DevOps 生命周期的一部分,因为它简化了合并和集成阶段。事实上,它也是 CI/CD 的必备实践。

与其它存在『长期分支』的功能分支策略相比,开发者可以通过一些小的提交创建『短期分支』。随着代码库复杂性和团队规模的增长,『基于主干的开发模式』有助于保持生产版本的流畅。-- Trunk-based Development | Atlassian

  • 上线模式

从部署分支上线

半自动化流程,适用于低频率部署,以及自动化测试不全面的项目

(A dot represents an MR merged into master. Green dots means good commits that passed e2e tests, and red dot means a buggy commit which should be avoided when deploying/rollback)

  1. 从 master 分支创建一个部署分支(RC)
  2. 构建部署分支(RC),并通知 QA 进行验证
  3. 如果发现任何问题
  • 开发者创建一个基于 master 分支的修复 MR
  • 经过代码审阅和合并过程将修复 MR 合入 master
  • 将 commits cherrypick 到部署分支(RC),再重新构建部署,并通知 QA 进行验证
  1. QA 验证通过后,将部署分支(RC)发布至线上,然后删除该分支(RC)
从主干分支上线

全自动化流程,适用于需要高频率部署,以及自动化测试较为全面的项目

(A dot represents an MR merged into master. Green dots means good commits that passed e2e tests, and red dot means a buggy commit which should be avoided when deploying/rollback)

  1. 定时部署: 每天或者每小时到了特定时间,部署机器人自动找到当前最新通过全部端到端测试的代码(特定的 commit hash),然后将之部署上线。
  2. 持续部署: 每当有新代码合并进主干分支时,部署机器人自动验证新代码是否通过所有端到端测试,以及是否与该项目相关,如果是则自动部署上线

为什么使用 trunk-based development?

  • 允许持续的代码集成(CI)

在『基于主干的开发模式』中,源源不断的提交合入主干分支。为每个提交添加自动化测试套件和代码覆盖率监控可以实现持续集成。当新代码合并到主干中时,会运行自动集成和代码覆盖测试以验证代码质量。

  • 确保持续的代码审查(CR)

『基于主干的开发模式』的快速、小型提交使代码审查成为一个更有效的过程。借助小型分支,开发人员可以快速查看和审查小的更改。与评审者阅读大面积代码变更的长期功能分支相比,这要容易得多。

  • 支持连续的生产代码发布(CD)

团队应该每天频繁地合并到主分支。『基于主干的开发模式』努力使主干分支保持“绿色”,这意味着它可以在每次提交合并后进行部署。自动化测试、代码收敛和代码审查,保证了基于主干的项目可以随时部署到生产环境中。

  • 更适用于大型 Monorepo 下的多人协作场景(scalable)

大型 Monorepo 下的多人协作场景更易出现代码冲突,不仅消耗的大量的人力解决冲突,还增加了『长期分支』合入『主干分支』引入 bug 的可能性。与其它存在『长期分支』的功能分支策略相比,开发者可以通过一些小提交创建『短期分支』进行快速迭代。因此,随着代码库复杂性和团队规模的增长,『基于主干的开发模式』也能保证顺畅的多人协作。

  • 线性的提交历史(Linear history)

Trunk-based development 更容易做到线性的 commit 历史,它有如下几个好处:

  1. 方便查看和跟踪历史记录
  2. 方便回溯变更,比如:Feature A 是在 Bugfix B 之前或者之后引入的?
  3. 方便排查 bug,比如:使用 Git bisect 二分排查,而非线性历史则难以操作
  4. 撤销变更,比如:当你发现一个有问题的 commit,简单的 revert 对应的 commit 即可,而非线性的历史会有很多跨分支的合并,使 revert 变得困难

有效的两个前提

  • 持续集成和测试

在每次代码合并前后,开发者都需要知道自己的代码对主干带来了什么影响,因此持续集成和测试的能力必不可少。

  • 功能开关

因为在基于主干开发时,大的功能被分解为小改动,因此对于还未完成而之后部分合并进主干的功能,我们需要功能开关来不让他们过早地暴露给用户。

功能开关通常是一套独立的控制系统,线上的代码有两套逻辑,然后通过实时读取功能开关的取值来决定是否隐藏或暴露某个功能。通常,我们在部署完一个功能相关的所有代码之后打开某个功能开关。然后当此功能已经稳定并且被永久加入产品后,会把功能开关和相关的逻辑代码删除掉。

参考

  • A tidy, linear Git history:https://www.bitsnbites.eu/a-tidy-linear-git-history/

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

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

相关文章

头歌:Ping客户端创建原始套接字(底部附全关完整答案)

头歌实践教学平台 (educoder.net)为Ping客户端创建一个原始类型的套接字原始套接字套接字(socket)是一个抽象层网络应用程序可以通过它发送或接收数据,可对其进行像文件一样的打开、读写和关闭等操作。套接字允许应用程序将I/O插入到网络中&a…

<C++>二叉树进阶

文章目录为什么要学这一节1. 二叉搜索树1.1 二叉搜索树概念1.2 二叉搜索树操作1.3 二叉搜索树的实现1.4 二叉搜索树的应用1.5 二叉搜索树的性能分析2. 经典题目2.1 最近公共祖先2.2 从前序与中序遍历序列构造二叉树2.3 二叉树的前序遍历(非递归)为什么要…

计算机组成原理复习:数据的表示和运算

计算机组成原理复习:数据的表示和运算2. 数据的表示和运算2.1 数制与编码2.1.1 数制:进位计数制及其相互转换2.1.2 编码:数值数据的编码与表示2.1.2.1 逻辑型数据2.1.2.2 字符型数据 之 ASCII码2.1.2.3 数值型数据 之 BCD码2.1.3 校验码——奇…

Part类 -- 上传文件

Part类 -- 上传文件一、核心方法1.1 HttpServletRequest 类方法1.2 Part 类方法二、代码示例前端搭配 form 表单:form input type “file”,允许通过浏览器选中一个文件上传给服务器。 Servlet 就支持处理这种上传文件的请求,把这个请求到的文…

安科瑞智能操控无线测温装置在江苏某化工产业园项目的应用

安科瑞 李亚俊 1 概述 江苏富强新材料有限公司是中国企业500强——山东金岭集团在江苏淮安盐化新材料产业园区投资设立的盐化工企业。公司将利用淮安丰富的盐矿资源和优越的发展环境,投资200亿元,建设120万吨/年离子膜烧碱项目、70万吨/年甲烷氯化物项…

vue新春游戏-拼手速抢车票小游戏,学习玩乐两不误,春节小游戏,新年小游戏

ue新春游戏-拼手速抢车票,老规矩,体验地址:http://game.pkec.net/word-ticket/。 写这个主要是前几天群里运营老师说咋没人写抢车票的,再加上我上一篇文章上了掘金一周,听说多上几次有证书,我还没搞到过掘金…

Go语言 函数传递:值传递 和 虚假的 “引用传递”

前言 其实从变量本身来说,go只有值传递,函数内的修改不会影响函数外。但有一种特例是指针,go可以传指针给函数,指针指向申请出来的实际内存,也就是保存元素的内存, 这样在函数内的修改,可以影响…

就算是TOP程序员,也有这些坏习惯

绝大多数程序员在职业生涯中,多多少少都会养成一些坏习惯,今天就来说一说身边最常见的一些坏习惯,也给刚入行的新朋友们提个醒,少走一些弯路。 那么,就让我们开始吧! 1.不注意适当休息 比如日常工作时、…

B端产品-登录功能设计

在项目启动初期,基本大家都是先从账号体系先开始着手设计的,那么B端的登录功能如何设计呢? 一、需求分析 B端的产品的用户基本上可以分为内部员工和客户,如果是客户使用,基本上都会有注册功能;如果是内部员…

C# Console.Read读取回车和换行

C#的Console.Read函数: 读取缓冲区中的数据,读取到一个字符时停止。 C#的Console.ReadLine函数 读取缓冲区中的数据,遇到回车时停止。 Enter键: 将行数据输入缓冲区,并且将回车符和换行符 加入缓冲区。 注意 Consol…

【H5UI库和二维码】一.H5UI库;二.加密技术;三.二维码

目录​​​​​​​ 一.H5UI库 1.使用方法: (1)页面中引入css文件 (2)页面中引入js文件 2.组件的用法 (2)按钮的使用:button。有三种类型(primary、danger、defaul…

MXNet的Faster R-CNN(基于区域提议网络的实时目标检测)《3》

前面了解到Faster R-CNN在实验中的效果很不错,以及对论文做了一个大概的了解,对此有兴趣的伙伴们也可以先浏览前面两篇文章:MXNet的Faster R-CNN(基于区域提议网络的实时目标检测)《1》MXNet的Faster R-CNN(基于区域提议网络的实时目标检测)《…

【Node】Node.js安装与配置(详细步骤)

Node.js安装与配置(详细步骤)一、安装Node.js1.1 下载1.2 安装1.3 环境变量二、验证是否安装成功三、修改模块下载位置3.1 查看npm默认存放位置3.2 在 nodejs 安装目录下,创建 “node_global” 和 “node_cache” 两个文件夹3.3 修改默认文件…

xd卡数据丢失原因和三种数据恢复方法介绍

xd卡适用于富士/奥林巴斯相机品牌,它能配合各式读卡器,方便的与个人电脑连接传输图像视频等。但是xd卡与其他类型的存储卡一样容易因各种原因出现数据丢失。如果您的xd卡出现了数据丢失的问题,不妨了解下这里给大家分析的xd卡数据丢失原因和具…

解决仓库产品管理痛点,选对条码工具至关重要

" 最近我们仓库管理遇到了很多问题,一方面 我们进出库的产品数量非常庞大,目前公司的条码扫描系统识别效率非常低,只能单个产品进行扫描,经常需要加班加点出入库,而且有些产品条码比较特殊,现在的扫描…

【LeetCode每日一题】——507.完美数

文章目录一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目示例】六【解题思路】七【题目提示】八【时间频度】九【代码实现】十【提交结果】一【题目类别】 数学 二【题目难度】 简单 三【题目编号】 507.完美数 四【题目描述】 对于一个 正整数&…

windows10安装goland

一、安装包 下载以下两个安装包: go语言二进制包: https://golang.google.cn/dl/ goland安装包 https://www.jetbrains.com/go/nextversion/ 二、安装go语言包 双击下载的语言包,直接next,选择安装路径(自己选择&am…

图的遍历(深度DFS与广度BFS)

文章目录图的遍历深度优先遍历思路邻接表邻接矩阵性能分析广度优先遍历思路邻接表邻接矩阵性能分析源代码图的遍历 **对有向图和无向图进行遍历是按照某种次序系统地访问图中的所有顶点, 并且使得每一个顶点只能访问一次. ** 对于图的遍历需要解决掉两个问题: 如果存在回路/环…

实力总结四类Bean注入Spring的方式

xml 方式 注解方式 Configuration Bean Import FactoryBean BDRegistryPostProcessor 源码 实战 一提到Spring,大家最先想到的是啥?是AOP和IOC的两大特性?是Spring中Bean的初始化流程?还是基于Spring的Spring Cloud全家桶呢…

Vue组件之间的通信

1、组件:是vue的重要的特征之一,可以扩展html的功能,也可以封装代码实现重复使用 2、组件的创建 (1)非脚手架方式创建: 1️⃣使用vue.extend创建组件 2️⃣使用vue.component注册组件 3️⃣在html页面…