增强版 Git Flow 模型

举报
Ocean2022 发表于 2022/05/21 11:22:59 2022/05/21
【摘要】 使用 Git 的最佳方式一直存在争议。那是因为 Git 本身只详细说明了基本的分支操作,这使得它的使用模式: 即分支模型——常常成为用户有意见的地方。虽然Git 分支模型能够帮助开发者减少其在更改代码库时带来的冲突。Git Flow,是一种经常推荐给 Git 用户的分支模型。 也许一开始你对 Git Flow 的逻辑很感兴趣,但是直到你在实践中遇到了一些障碍。 毕竟,有无数的变量在起作用,没...

使用 Git 的最佳方式一直存在争议。那是因为 Git 本身只详细说明了基本的分支操作,这使得它的使用模式: 即分支模型——常常成为用户有意见的地方。虽然Git 分支模型能够帮助开发者减少其在更改代码库时带来的冲突。

Git Flow,是一种经常推荐给 Git 用户的分支模型。 也许一开始你对 Git Flow 的逻辑很感兴趣,但是直到你在实践中遇到了一些障碍。 毕竟,有无数的变量在起作用,没有一个单一的分支模型能在所有情况下都能很好地工作。

但是,值的高兴的是作为经典 Git Flow 模型的一个变体,增强的 Git Flow模型版本简化了 Git Flow 中更常见的操作,并保留了主要优点。

经典 Git Flow 模型的辉煌与苦难

自从我发现 Git Flow 在开发具有显著价值产品时是多么出色以来,我一直是 Git Flow 的强烈倡导者。

一个显著的价值增长需要大量的时间来证明,就像在基于 scrum 的开发中通常使用的两周以上的 sprint。

当产品仍处于初始开发阶段时,即,没有产品,也没有产品的真正用户时,团队可以把所有的东西都放在主分支中。事实上,这是非常好的:这种策略允许最快的开发速度。但是在生产环境中情况会发生变化。

例如,如果在生产中有一个需要立即修复的关键 issue,那么对于开发团队来说,为了部署修复的代码而不得不回滚现有已经完成的代码。在没有进行适当测试的情况下部署代码,不管代码被认为是不成熟的还是开发良好的,显然是不可取的。

这就是分支模型的特点,包括 Git Flow。任何复杂的分支模型都应该回答以下问题:

  • 如何将下一个版本与人们当前使用的版本隔离开来

  • 如何用下一个版本更新该版本;

  • 如何将任何关键错误的修复代码引入当前版本。

Git Flow 通过分离“main”分支(生产或“当前版本”分支)和“dev”(开发或“下一个版本”分支)分支,并提供有关使用 feature/release/hotfix 分支的所有规则,来解决这些基本的场景。它有效地解决了 release 的开发工作流中的许多令人头疼的问题。

但是,即使有非常适合经典 Git Flow 模型的项目,我也遇到了它可能带来的典型问题:

  • Git Flow 很复杂,有两个长期存在的分支,三种临时分支,以及分支之间如何处理的严格规则。这种复杂性更容易导致错误,并增加了修复错误所需的成本。

  • release 和 hotfix 分支需要“双重合并”——进入main分支,然后进入devlop分支。有时你会忘记兼顾两者。您可以使用脚本或 VCS GUI 客户端插件使 Git Flow 分支更容易,但必须首先为给定项目中涉及的每个开发人员的每台机器设置它们。

  • 在 CI/CD 工作流中,一个发布通常会有两个最终版本——一个来自 release 分支本身的最新提交,另一个来自合并提交到 main 分支的提交。严格地说,应该使用来自 main 的。但这两个通常是相同的,可能会造成混淆。

增强版 Git Flow

在产品的第一次公开发布之前,为了开发工作流的速度和简单性,直接将所有更改提交到 main 分支是绝对有意义的。因为还没有产品,所以团队不可能需要尽快修复产品 bug。因此,在这个阶段执行传统 Git Flow 模型所建议的分支管理是多余的。

然后我们接近了最初的 release 版本,在那之后,我们将不再愿意直接提交到 main 分支。我们进展得很快,业务优先级没有给建立一个坚如磐石的开发过程留下太多空间。它具有足够的自动化测试,使我们有信心保持我们的主要分支处于准备发布的状态。

这似乎是经典 Git Flow 模型的一个有效案例。有了独立的 main 分支和 devlop 分支。

但是,后来我做了一些变化。起初在我看来,对 Git Flow 做一些“补丁”有点过于冒进了。我认为这样可能会打破 Git Flow 主要的思想,从而达不到目标。但经过进一步的思考,我意识到这些调整实际上并没有破坏 Git Flow。同时,他们解决了上面提到的所有问题,使之成为一个更好的 Git 分支模型。

img

下面,我将和大家分享这套方法,帮助开发者克服传统 Git Flow 的缺点。

与传统 Git Flow 的相似之处: 开发隔离

对于增强的 Git Flow 中的工作隔离,仍然有两个长期存在的分支:main 和 development。

经典的 Git Flow feature 分支没有正式的命名方案。当 feature 准备好时,只需要从 devlop 分支出来并合并回去进行开发。团队可以使用任何他们喜欢的命名约定,或者只是希望开发人员使用比“my-branch”更具有描述性的名称。增强的 Git Flow 也是如此。

压缩合并

我强烈建议在 feature 分支中使用压缩合并,以便在大多数时候保持良好的线性历史记录。如果没有它,当团队同时处理少量的 feature 分支时,git graph(git log -graph)日志会显得比较草率:

img

但即使你对这种情况下的视觉效果没有意见。没有压缩,提交的历史视图-其中包括普通的 git 日志(没有-graph)和 一些相当不连贯的 log,即使是最简单的合并场景:

img

使用压缩合并需要知道的是原有的 feature 分支提交历史会丢失。
在这里插入图片描述

与经典 Git 流程的区别: Releases and Hotfixes

让我们来看看发布周期,因为这是你要做的主要事情。当我们想要发布开发中积累的内容时,它严格来说是 main 的超集。在此之后,经典和增强的 Git 流之间的最大区别就开始了。

img

Git Flow 增强版中的 release 分支

在 release 方面,使用增强的 Git Flow 的每一步都与经典的 Git Flow 不同:

  1. release 是基 于main 分支的,而不是基于 devlop 分支的。你可以用一些有意义的东西标记 main 分支的当前的 tip。我采用了 ISO 8601 格式中基于当前日期的标签,前缀是“v”-例如: v2020-09-09
  • 如果一天中碰巧有多个版本(例如修补 issue),则格式可以根据需要附加一个连续的数字或字母。
  • 请注意,标签通常并不对应于发布日期。它们仅仅是为了迫使 Git 保持对下一个发布过程开始时main分支的参考。
  1. 使用 git Push origin <the new tag name> 来 push tag。

  2. 在此之后,可能会有一个意外:如果要删除本地的 main 分支。

  • 所有提交到 main 的操作仍然是安全的——我们通过在上一步标记 main 来保护它们不被垃圾收集。每一个提交(甚至是修补程序)也是开发的一部分。

  • 只需要确保团队中只有一个人在执行这一任务:这就是所谓的“发布经理”角色。发布经理通常是最有经验和/或最资深的团队成员,但是团队应该明智地避免任何特定的团队成员永久地承担这个角色。

  1. 在开发分支的提示提交处创建一个新的本地主分支。

  2. 使用 git Push -force 来推动这个新结构,因为远程仓库不会这么容易地接受这样一个“剧烈的变化”。同样,在这种情况下,这并不像看起来那么不安全,因为:

  • 我们只是将主分支指针从一个提交移动到另一个提交。
  • 每次只有一个特定的团队成员在做这个更改。
  • 每天的开发工作都在开发分支上进行,所以这样移动 main 不会干扰任何人的工作。
  1. 将其部署到环境中并对其进行测试。任何修复都直接指向主分支,因此它将开始偏离开发分支。
  • 与此同时,您可以开始在开发分支中开发新版本,这与在经典 Git Flow 中看到的优势相同。
  1. 当您的新版本被认为足够稳定时,将最终版本部署到生产环境中,并进行一次主开发合并,以获得所有的修复。

增强 Git Flow 模型中的 Hotfixes

Hotfixes 的情况有两方面。如果你正在做一个热修复时,例如,团队正在开发分支中准备一个新版本,当它们准备好时,需要部署到生产环境。

作为最后一步,从 main 中选择提交来开发,以确保下一个版本将包含所有修复。如果您需要提交几个热修复程序,您可以通过创建并应用一个补丁而不是多次选择补丁来节省精力—特别是如果您的 IDE 或其他 Git 工具可以提供便利的话。试图在初始版本发布后将合并主分支压缩到开发分支,很可能会与开发分支的独立进程产生冲突,所以我不建议这样做。

在 relase 期间处理修补程序。例如,当您只是强行推入 main 分支并仍在准备新版本时,是增强版 Git Flow 中最薄弱的地方。根据发布周期的长度和需要解决的问题的严重程度,始终以在新发布版本中包含修复为目标——这是最简单的方法,而且根本不会打乱整个工作流。

如果这是一个不可能的,你必须快速引入一个修复,你不能等待新版本的发布-然后准备一个有点复杂的 Git 过程:

  1. 创建一个分支—我们将其称为“new-release”,但是您的团队可以在这里采用任何命名约定。
  2. 在您先前为当前 release 创建的标记提交时,删除并重新创建本地主分支。
  3. 向 main 引入必要的修复,部署到环境,并进行测试。一旦准备好了,就部署到生产环境中。
  4. 将当前主版本的更改通过补丁到新版本。
  5. 然后,重新执行发布过程:在当前主干的顶端标记并推送标记,在新发布分支的顶端删除并重新创建本地主分支,然后强制推送。
  • 您可能不需要前面的标记,所以可以删除它。
  • 新发布的分支现在是多余的,所以您也可以删除它。
  1. 您现在应该可以像往常一样使用新发行版了。通过传播紧急修补程序从主开发通过 cherry pick 或补丁完成。

img

CI/CD 在增强 Git Flow 模型中的设置

并不是每个项目都需要专用的开发环境。在每台开发人员机器上设置复杂的本地开发环境可能很容易。

在开发分支上运行测试、测量测试覆盖率和计算复杂性度量,通过在错误进入执行阶段之前很好地捕获它们,通常可以降低错误的成本。

我发现一些 CI/CD 模式在与增强的 Git Flow 结合使用时特别有用:

  • 如果您需要一个开发环境,请设置 CI,以便在每次提交到开发分支时进行构建、测试和部署。如果您有 E2E 测试,并且它对您的情况有意义,那么也可以在这里进行 E2E 测试。

  • 在每次提交到主分支时,设置 CI 来构建、测试和部署到环境。在这一点上,端到端测试也非常有益。

在两个地方都使用端到端测试似乎是多余的,但是请记住,修补程序不会在开发过程中发生。在提交到 main 时触发 E2E,将测试修复程序和每天的更改,但在提交到开发时触发将更早地捕获bug。

  • 以一种允许您的团队根据手工请求将构建版本从主环境部署到生产环境的方式配置 CI。

img

这些模式相对简单,但提供了支持日常开发操作的强大机制。

改进和可能存在的限制

增强的 Git Flow 并不适合所有人。它确实利用了有争议的策略,用武力推动主要分支,所以纯粹主义者可能会怨恨它。然而,从实际的角度来看,这并没有什么问题。

如前所述,修补程序在发布期间更具挑战性,但仍然是可能的。在适当关注 QA、测试覆盖率等方面,这些不应该经常发生,所以在我看来,与传统的 Git 流相比,增强的 Git 流的整体好处是一个有效的权衡。我很想知道增强的 Git 流在更大的团队和更复杂的项目中如何发挥作用,在这些项目中修补程序可能会更频繁地出现。

我对增强的 Git 流模型的积极体验也主要围绕着封闭源代码的商业项目。这对于一个开源项目来说可能是有问题的,因为拉请求通常是基于源代码树的旧版本派生的。解决这个问题没有技术障碍,只是可能需要比预期更多的努力。我非常欢迎那些在开源领域拥有丰富经验的读者的反馈,因为你们了解增强的 Git 流在这种情况下的适用性。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。