yuff100

V1

2022/05/02阅读:55主题:极简黑

Git进阶系列 | 2. Git中的分支策略

Git是最流行的代码版本控制系统,这一系列文章介绍了一些Git的高阶使用方式,从而帮助我们可以更好的利用Git的能力。本系列一共8篇文章,这是第2篇。原文:Branching Strategies in Git[1]

几乎所有的版本控制系统(VCS)都有某种类型的分支支持。简而言之,分支意味着可以创建一个新的、独立的容器而离开主开发线,并继续在那里工作。通过这种方式,可以在不破坏生产代码库的情况下进行试验和尝试。Git用户知道Git的分支模型非常特殊,而且非常强大,这是Git最酷的功能之一。Git的分支模型快速且轻量,在分支之间来回切换的速度与创建或删除分支一样快。可以说Git鼓励使用大量分支和合并的工作流。

Git把创建多少分支以及合并的频率完全交给了开发者决定。如果你独自编写代码,可以自由选择什么时候创建新分支,以及保留多少个分支。但当我们在团队中工作时,情况就不同了。Git提供工具,但是团队需要负责以最佳方式使用这一工具!

本文将讨论分支策略和不同类型的Git分支,还会介绍两种常见的分支工作流: Git Flow和GitHub Flow。

Git进阶系列:

  1. 创建完美的提交
  2. Git中的分支策略(本文)
  3. 基于Pull Request实现更好的协作
  4. 合并冲突
  5. Rebase vs Merge
  6. 交互式Rebase
  7. Git中的Cherry-pick提交
  8. 用Reflog恢复丢失的提交

团队合作: 制定规则

在探索构建发布和集成变更的不同方法之前,先来讨论一下规则。如果在团队中工作,需要对项目的通用工作流和分支策略达成一致,最好将其写下来,让所有团队成员都能看到。

诚然,并不是每个人都喜欢编写文档或指导方针,但将最佳实践记录在案不仅可以避免错误和冲突,还有助于培训新团队成员。解释分支策略的文档将帮助他们理解团队是如何工作的,以及如何处理软件版本。

以下是我们自己文档中的一些例子:

  • master代表当前的公开发布分支
  • next表示下一个公开发布分支(这样我们就可以在master上提交修补程序而不会引入不必要的更改)
  • 特性分支被分组在feature/
  • WIP分支被分组在wip/下(可以用来创建个人WIP的“备份”)

不同团队可能对这些规则有不同看法(例如“wip”或“feature”组),这肯定会反映在他们自己的文档中。

集成变更和结构化发布

当我们考虑如何在Git仓库中使用分支时,应该从考虑如何集成变更和如何构建发布开始。所有这些话题都是紧密相连的,为了更好的理解不同的选择,我们来看下两种不同的策略。下面的例子是为了说明极端情况会怎么样,从而帮助你思考如何设计自己的分支工作流:

  • 主线开发
  • 状态分支、发布分支和特性分支

第一个选择可以被描述为“始终集成”,基本上可以归结为: 始终将自己的工作与团队的工作集成在一起。在第二种策略中,收集自己的工作并发布,即多个不同类型的分支进入预发阶段。两种方法各有利弊,两种策略都适用于某些团队,但不适用于另一些团队,大多数开发团队在这两个极端之间工作。

我们从主线开发开始解释这个策略是如何工作的。

主线开发

之前提到过,这种方法的座右铭是“总是集成”。只有一个单独的分支,每个人都在主线上开发:

记住,这是一个简化的例子,我怀疑在现实世界中是否有任何团队能够使用如此简单的分支结构。然而,理解这个模型的优点和缺点确实有帮助。

首先,只有一个分支,因此很容易跟踪项目中的变化。其次,提交必须相对较小: 在不断集成到生产代码的环境中,不能冒险进行大而臃肿的提交。因此,团队的测试和QA标准必须是一流的!如果没有一个高质量的测试环境,主线开发方法就不适合。

状态分支、发布分支和特性分支

下面看看另一种情况,如何使用多个不同类型的分支。每个分支都有不同的工作: 新特性和实验代码保存在自己的分支中,发布可以在自己的分支中规划和管理,甚至开发流程中的各种状态也可以用分支来表示:

记住,这完全取决于团队和项目的需求。虽然这种方法一开始可能看起来很复杂,但完全是一个练习和习惯的问题。

现在,让我们更详细地探讨两种主要的分支类型: 长期分支(long-running branches)和短期分支(short-lived branches)。

长期分支

每个Git仓库至少包含一个长期分支,通常称为mastermain。当然,团队可能会决定在项目中使用其他长期分支,例如类似于开发(develop)、生产(production)或预发(staging)分支。所有这些分支都有一个共同点: 存在于整个项目生命周期中。

mastermain这样的主线分支是长期分支的一个例子。此外,还有所谓的集成分支,如开发或预发。这些分支通常代表项目发布或部署过程中的状态。如果代码在开发生命周期中经历了不同的状态(例如,从开发阶段到预发阶段再到生产阶段),在分支中的这个镜像结构也是有意义的。

关于长期分支的最后一点: 大多数团队都有一个类似于“不要直接向长期分支提交内容”的规则,通常通过merge或rebase来集成。制定这项规则有两个主要原因:

  • 质量: 不应将未经测试或评审的代码发布到生产环境中。
  • 捆绑发布和调度: 可能希望分批发布新代码,甚至提前安排发布。

接下来是短期分支,通常为特定目的而创建,然后在代码集成后删除。

短期分支

与长期分支相反,短期分支是为临时目的而创建的,一旦它们完成了职责并且代码被集成到主线(或另一个长期分支)中,就会被删除。有许多不同的原因需要创建短期分支,例如致力于新的实验性特性,修复bug,重构代码,等等。

短期分支通常基于长期分支创建。假设我们开始有一个新特性的开发,可以基于长期的主分支创建新特性分支。在若干次提交和测试之后,工作完成,新特性可以集成到主分支中,并且merge或rebase之后,可以删除特性分支。

两种流行的分支策略

最后我们看一下两种流行的分支策略: Git Flow和GitHub Flow。虽然不同的团队可能会决定完全不同的分支策略,但这两种流行的策略可以作为团队分支策略的灵感来源。

Git Flow

Git Flow[2]是一个著名的分支策略,其中main分支总是反映当前的生产状态,此外还有第二个长期分支,通常称为develop。所有特性分支都从这里创建,并将合并到develop中。而且,该分支是新发布的起点: 开发人员创建一个新的release分支,在上面工作、测试、提交bug修复。一旦一切正常,并且确信已经准备好投入生产,就将它合并回main。作为最后一步,在main上为发布添加一个标签,并删除release分支。

Git Flow对于可打包的软件(桌面)应用程序或库来说工作得很好,但对于网站项目来说似乎有点过头了。在这类项目里,main分支和release分支之间通常区别不大,分不同的分支没有特别大的好处。

如果使用的是像Tower这样的Git桌面GUI,可以在界面中找到可能的操作,不需要记住任何新命令:

GitHub Flow

如果团队遵循短生产周期和频繁发布的持续交付方式,建议看看GitHub Flow[3]

这种方式非常精益和简单: 有一个长期分支,即默认的main分支,任何正在做的工作都有自己独立的分支,无所谓是新特性、bug修复还是重构。

“最好”的Git分支策略是什么?

如果问10个不同的团队他们是如何使用Git分支的,可能会得到10个不同的答案。没有所谓的“最佳”分支策略,也没有每个人都应该采用的完美工作流。为了找到最适合团队的模型,应该坐下来分析所做的项目,讨论发布策略,然后决定一个分支工作流,从而以最好的方式支持我们的项目。

如果想更深入了解高级Git工具,可以免费查看“Advanced Git Kit[3]”: 这是关于分支策略、交互式Rebase、Reflog、子模块等主题的短视频集合。

References:
[1] Branching Strategies in Git: https://css-tricks.com/branching-strategies-in-git/
[2] A Successful Git Branching Model: http://nvie.com/posts/a-successful-git-branching-model/
[3] GitHub Flow: https://guides.github.com/introduction/flow/

你好,我是俞凡,在Motorola做过研发,现在在Mavenir做技术工作,对通信、网络、后端架构、云原生、DevOps、CICD、区块链、AI等技术始终保持着浓厚的兴趣,平时喜欢阅读、思考,相信持续学习、终身成长,欢迎一起交流学习。
微信公众号:DeepNoMind

- END -

分类:

后端

标签:

Git

作者介绍

yuff100
V1

俞凡,公众号DeepNoMind