Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >一个成功的Git分支模型

一个成功的Git分支模型

作者头像
云深i不知处
发布于 2022-10-05 08:44:24
发布于 2022-10-05 08:44:24
76800
代码可运行
举报
文章被收录于专栏:测试基础测试基础
运行总次数:0
代码可运行

本文翻译自Vincent Driessen的:A successful Git branching model

前言

本文所讲的开发模型是我在Git诞生后不久的2010年构思的,距今已有十余年。在这10年里,git-flow(本文中列出的分支模型)在许多软件团队中非常流行,以至于人们开始将其视为某种标准,但不幸的是,它也被视为一种教条或万灵药。

在这10年间,Git本身已经风靡全球,而且web应用程序越来越成为最流行的软件应用类型,至少在我的认知中是这样的。Web应用程序通常是连续交付的,而不是回滚的,而且你不必支持多个版本的软件。

这不是我十年前写博客时想的那种软件。如果您的团队正在持续交付软件,我建议采用更简单的工作流(如GitHub流),而不是试图将 git-flow 硬塞进您的团队。

然而,如果您正在构建显式版本化的软件,或者如果您需要在野外支持软件的多个版本,那么git-flow可能仍然像过去10年一样适合您的团队。如果是这样,请继续阅读。

总之,永远记住,万灵药是不存在的,你要结合自己的需求背景做决定。

在这篇文章中,我介绍了大约一年前我为我的一些项目(包括工作和私人项目)引入的开发模型,结果证明它非常成功。我想写这篇文章已经有一段时间了,直到今天我才腾出时间来。在这篇文章中我不会谈论任何项目的细节,只谈论分支策略和发布管理。

为什么是Git?

有关Git相对于集中式源码控制系统的优缺点,网络上讨论得如火如荼,我在这里就不再赘述。作为一名开发人员,我本人是更喜欢GitGit确实改变了开发人员对合并和分支的看法。在Git之前,合并分支一直被认为是一件让人担惊受怕的事情。

但有了Git之后,这些操作变得非常简单,并且它们也成为日常工作流程的核心部分之一。例如,在CVS/Subversion书籍中,分支和合并通常在属于面向高级用户的知识点而被放在靠后的章节中讨论,而在Git相关的书籍中,这些被视为基础知识而放置在第三章进行讨论。

简单和重复的特性带来的结果是:分支与合并不再是什么值得害怕的东西。分支/合并被认为对于版本管理工具比其他功能更重要。

工具已备,让我们直接看开发模型吧。我将在这里介绍的模型基本上只不过是一组程序,每个团队成员都必须遵循这些程序才能形成托管软件开发过程。

分布又集中

Git 属于一种分布式版本控制系统Distributed Version Control System),因此 Git 中并没有一个真正意义上的中央仓库。但我们通常把 每个Git 用户所熟知的 origin 视作中央仓库,这种设定非常契合我的分支模型。

每个人都可以从 origin 拉取代码或向 origin 推入代码。但除了这种中心化的推-拉关系之外,每个开发人员还可以和其他人组成子团队,子团队成员之间互相拉取对方的代码。这种模式对多个开发者协作开发一个大型的需求更加有利。例如上图中,有Alice和Bob、Alice和David、Clair和David的子团队。

从技术上来说,这只意味着Alice定义了一个名为bob的Git远程,指向bob的仓库,反之亦然。

主分支

中央仓库拥有两个永久的主要分支:

  • master
  • develop

其中,每个 Git 用户都耳熟能详的 origin/master 分支,承载着通过了测试并准备发布到生产环境上的最新代码。

而与之对应的 origin/develop 分支,也就是开发分支,这个分支上的代码一般是由各个开发人员针对下个版本开发合并而来,因此也有些人将其称为“集成分支”。这个分支是构建和测试的基础。

当开发分支中的代码经过测试达到可上线状态,那么开发分支的所有更改都应该以某种方式合并回master 分支,并用发布号标记。后文中,我们将进一步详细讨论如何做到这一点。

每次将更改合并回 master 时,理论上都将诞生一个新的生产版本,因此向 master 合并代码往往是非常严谨的一件事情。从而,从理论上来说,每当master分支有一个提交操作,我们就可以使用Git钩子脚本来自动构建并且发布软件到生产服务器

辅助分支

除了 masterdevelop 这两个主要分支之外,我们的开发模型还会使用多个次要分支来支持多人并行开发模式。与主要分支不同的是,这些次要分支生命周期是有限的,我们通常是会为某个需求而创建一个分支并在需求完成之后删除它。

我们可以使用的辅助分支类型有:

  • Feature branches
  • Release branches
  • Hotfix branches

这些分支都有其特定用途,并受到严格约束,例如哪些分支是原始分支,哪些分支是代码合并的目标分支等。后文我将简短地展开论述一下这个问题。

Feature branches

Feature branches,可以称之为特性分支,特性分支(有时被称为主题分支)用于为近期或远期的未来版本开发新特性(或新功能)。当一个新特性开始开发时,它将被纳入的目标版本可能在那时还不清楚。特性分支的本质是,只要新特性还在开发中,它就会一直存在,但最终会被合并回 develop 分支中(以明确地将新特性添加到即将发布的版本中)或被丢弃。

Feature 分支基于 develop 分支,合并到 develop 分支,命名上比较自由,但不得使用masterdeveloprelease-*hotfix-*等。

创建 Feature 分支

当开始开发一个新功能时,请从 develop 分支初始化一个特性分支:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# Switched to a new branch "myfeature"
$ git checkout -b myfeature develop

合并 Feature 分支

开发完成的功能可能会合并到 develop 分支中,以明确将其添加到即将发布的版本中:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 切换到 develop 分支
$ git checkout develop
# 将 myfeature 分支合并到 develop 分支
$ git merge --no-ff myfeature
# 删除 myfeature 分支
$ git branch -d myfeature
# 
$ git push origin develop

--no-ff 标志会导致合并始终创建一个新的提交对象,即使合并可以快速执行。这样可以避免丢失有关功能分支历史存在的信息,并将所有添加功能的提交组合在一起。对比情形如下:

在后一种情况下,无法从Git 历史中看到哪些提交对象一起实现了一个特性,你必须手动读取所有日志消息,而且这种情况下还原整个特性(即一组提交)确实是一个令人头痛的问题,而如果使用 --no-ff 标志,这个问题就容易解决多了。

尽管使用 --no-ff 标志将创建更多的提交对象,但收益远大于成本。

Release branches

Release branches,被称之为发布分支,这个分支用来支持新产品或新功能的准备工作。发布分支允许进行小的错误修复和元数据(版本号、构建日期等)准备工作。当 Release 分支创建后,develop 分支就可以腾出来去承接新的需求了。

develop 分支中分离出一个新的 Release 分支的关键前提是 develop 分支达到了新发行版本的期望状态,也就是所有针对这次即将发布的版本而开发的代码都必须合并进来,至于为后续版本开发的功能则要等 Release 分支创建后再合并进 develop 分支。

随着发布分支的创建,即将发布的版本会被分配一个版本号,这个版本号会与之前的版本号做区分。在这之前,develop 分支反映了“下一个版本”的变化,但在Release 分支开始之前,“下一版本”最终会变成0.3还是1.0还不清楚。这个版本号命名是在Release分支创建时做出的,并严格遵守项目关于版本号的延续命名习惯。

Release分支是从develop分支创建的。例如,假设版本1.1.5是当前的生产版本,我们即将推出一个大型版本。开发状态已经为“下一个版本”做好了准备,我们已经决定这将成为1.2版(而不是1.1.6或2.0版)。因此,我们创建相应的Release分支 ,并为Release分支机构指定一个反映新版本号的名称:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 切换到一个新分支 release-1.2
$ git checkout -b release-1.2 develop
# 进行版本号碰撞--提示:Files modified successfully, version bumped to 1.2.
$ ./bump-version.sh 1.2
# [release-1.2 74d9424] Bumped version number to 1.2
# 1 files changed, 1 insertions(+), 1 deletions(-)
$ git commit -a -m "Bumped version number to 1.2"

至此,Release 分支创建完成,并打了标记以备将来参考。

您还可以使用-s-u <key>标志对标记进行加密签名。

不过,为了保存在Release分支中所做的更改,我们需要将这些更改合并回develop分支中:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 切换到 develop 分支
$ git checkout develop
# 将 release-1.2 分支合并到 develop 分支
$ git merge --no-ff release-1.2

这一步很可能会导致合并冲突,如果遇到冲突,解决冲突后再重新提交即可。

以上工作全部完成后,Release分支的使命就完成了,我们可以将其删除:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ git branch -d release-1.2

Hotfix branches

Hotfix branches,热修复分支,与Release分支非常相似,也旨在为新的生产版本做准备,尽管是计划外的。它们通常是为了解决线上问题而创建的临时分支。

Hotfix 分支基于 master 分支,合并到 master 分支和 develop 分支,命名上一般采用 hotfix-* 形式。

在实际工作中,通常由特定人员在 Hotfix 分支上快速修复线上问题,而其他人员的正常开发工作继续进行。

创建Hotfix分支

Hotfix分支是从master分支创建的。例如,假设1.2版是当前正在运行的生产版本,并且由于严重的错误而导致问题。与此同时,随着新需求的开发,develop分支仍在不断更新中。因此,我们可以分支出一个Hotfix分支并开始修复问题:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 切换到 hotfix-1.2.1 分支
$ git checkout -b hotfix-1.2.1 master
# 更新版本号--Files modified successfully, version bumped to 1.2.1.
$ ./bump-version.sh 1.2.1
# 初始提交
$ git commit -a -m "Bumped version number to 1.2.1"

分支创建后,记得更新版本号。

接下来,修复问题并提交你的代码吧。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ git commit -m "Fixed severe production problem"
# [hotfix-1.2.1 abbe5d6] Fixed severe production problem
# 5 files changed, 32 insertions(+), 17 deletions(-)

终结Hotfix分支

问题修复完成后,bugfix分支需要合并回master分支,也需要合并回develop分支,以确保这些代码也包含在下一版本中。

首先,更新 master 分支并标记特性

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 切换到 master 分支
$ git checkout master
# 将 hotfix-1.2.1 合并到 master 分支
$ git merge --no-ff hotfix-1.2.1
# 打标记
$ git tag -a 1.2.1

您还可以使用-s-u <key>标志对标记进行加密签名。

接下来,将bugfix分支合并到develop分支:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 切换到 develop 分支
$ git checkout develop
# 将 hotfix-1.2.1 合并到 develop 分支
$ git merge --no-ff hotfix-1.2.1

此处规则的一个例外是: 如果存在一个release分支,那么应该把hotfix合并到这个release分支,而不是合并到develop分支。当release分支完成后, 将bugfix分支合并回release分支同样会使得bugfix被合并到develop分支。(如果在develop分支的工作急需这个bugfix,等不到release分支的完成,那你也可以把bugfix合并到develop分支)

最后,删除 bugfix 分支:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ git branch -d hotfix-1.2.1

总结

虽然这个分支模型并没有什么新的令人震惊的东西,但这篇文章开头的图表在我们的项目中已经被证明是非常有用的。它形成了一个优雅的思维模型,易于理解,并引领团队成员达成对分支和发布过程的共识。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-09-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
你是如何玩Git分支模型的呢?
对于Git与其他集中式代码管理工具相比的优缺点的全面讨论,请参见这里。这样的争论总是喋喋不休。作为一个开发者,与现今的其他开发工具相比较,我更喜欢Git。Git真得改变了开发者对于合并和分支的思考。我曾经使用经典的CVS/Subversion,然而每次的合并/分支和其他行为总让人担惊受怕(“小心合并里的冲突,简直要命!”)。但是对于Git来说,这些行为非常简单和搞笑,它们被认为是日常工作中的核心部分。例如,在很多CVS/Subversion书里,分支与合并总是在后面的章节中被讨论(对于高级用户使用),然而在每个Git书中,在第3章就已经完全涵盖了(作为基础)。简单和重复的特性带来的结果是:分支与合并不再是什么可以害怕的东西。分支/合并被认为对于版本管理工具比其他功能更重要。关于工具,不再多说,让我们直接看开发模型吧。这个模型并不是如下模型:在管理软件开发进度方面,面对每个开发过程,每个队员必须按一定次序开发。
chengcheng222e
2021/11/04
5780
猫头鹰的深夜翻译:开发者必须了解的分支发布模型
想要深入了解Git和中心化代码版本管理系统的优缺点比较,可以在网上自行查询,这个话题一直争论不休。作为一个开发者,我更倾向于使用Git。Git确实改变了开发者对代码合并和分支管理的认识。作为一个使用过传统的CVS工具的人,合并/开分支是一个比较恐怖的行为,迫不得已才执行一次。
眯眯眼的猫头鹰
2019/11/08
5920
猫头鹰的深夜翻译:开发者必须了解的分支发布模型
Git 分支管理的 23 条军规
1 GIT,在技术层面上,绝对是一个无中心的分布式版本控制系统,但在管理层面上,我建议你保持一个中心版本库。
DevOps时代
2019/08/28
7320
Git 分支管理的 23 条军规
老曹眼中的Git
Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。大神就是大神,在开发了Linux之后,Git 是又一抗鼎之作。这是唯一的理由么?
半吊子全栈工匠
2018/08/22
5920
老曹眼中的Git
Git基础知识(七)--分支开发工作流
大型项目中,通过类似的方式使分支具有不同级别的稳定性。当它们具有一定程度的稳定性后,再把它们合入更高级别的稳定性分支中。使用多个长期分支的方法并非必要,但是当你在一 个非常庞大或者复杂的项目中工作时,就会提供很大的帮助。
zx钟
2019/07/19
1.3K0
Git 分支管理策略汇总
最近,团队新入职了一些小伙伴,在开发过程中,他们问我 Git 分支是如何管理的,以及应该怎么提交代码?
AlwaysBeta
2022/11/11
1.4K0
Git 分支管理策略汇总
代码版本管理规范
git 流程模式有两种:一种是Git flow工作流,一种是Github flow工作流。
机械视角
2020/08/17
3K0
使用 git-flow 自动化你的 git 工作流
上面的图看不懂没关系(我也不懂==),今天讲的是根据这个分支模型开发的 git-flow 命令行工具。只需要记住几个简单的命令,就能在工作中慢慢理解和应用这个分支模型~
savokiss
2019/11/25
1K0
基于 git flow + gitlab 协作开发:02 解决问题
上一篇文章中我们提到了在一个周维度或者月维度发布产品的小型协作项目中,会遇到各类协作上的问题,随着发布的越来越紧凑,问题也就越来越突出。本文主要对上一篇文章中提到的问题解决方案做细化,让大家可以清楚的知道如何通过合理的 git 工作流来解决这些问题,让原来发布时的手忙脚乱不再出现。通过 git flow 我们可以对项目做一个分支模型管理:
我与梦想有个约会
2021/03/13
1.2K0
Git 版本控制之 GitFlow
最近在着手制定开发规范,想要把项目正规高效的跑起来。计划引入 Git 版本控制,Git-Flow 便成为了首选。因为之前并没有过多接触,所以先花些时间摸索一下。
程序猿DD
2018/12/28
9730
Java程序员学习资料—Git Flow
在Java程序开发中的定制开发规范,想要把项目正规高效的跑起来。引入 Git 版本控制,Git-Flow 便成为了首选。今天动力节点Java学院来带你了解一下。
动力节点Java培训
2019/05/22
5380
Java程序员学习资料—Git Flow
Git flow 规范
VV采用标准的Git flow,下面将从工作流图与抽象模型两个方面,来描述与规范 Git flow。
jwangkun
2021/12/23
3.1K0
Git flow 规范
开发流程与版本管理规范(上)
如非特殊说明,所有产品的版本号将遵循 主版本.次版本.BuildNumber 的规则。
用户1348170
2021/07/09
2.9K0
GitHub 系列之「团队合作利器 Branch」1.什么是分支?2.分支的常用操作3.基本的团队协作流程4.Git Flow
Git 相比于 SVN 最强大的一个地方就在于「分支」,Git 的分支操作简直不要太方便,而实际项目开发中团队合作最依赖的莫过于分支了,关于分支前面的系列也提到过,但是本篇会详细讲述什么是分支、分支的具体操作以及实际项目开发中到底是怎么依赖分支来进行团队合作的。
Python攻城狮
2018/08/23
1K0
GitHub 系列之「团队合作利器 Branch」1.什么是分支?2.分支的常用操作3.基本的团队协作流程4.Git Flow
如何克服解决Git冲突的恐惧症?(Git分支策略)
主分支只用来分布重大版本,日常开发应该在另一条分支上完成。我们把开发用的分支,叫做Develop。
前端黑板报
2020/12/10
6410
如何克服解决Git冲突的恐惧症?(Git分支策略)
GitFlow 代码管理模型实战
Git Flow定义了一个项目发布的分支模型,为管理具有预定发布周期的大型项目提供了一个健壮的框架。
耕耘实录
2021/03/20
6310
git分支管理
命名: master、develop、feature以feature/功能名、release以release/功能名、hotfix以hotfix/bug名
OPice
2020/01/15
5610
Git秘籍: Git and Git Flow Cheat Sheet
注意:git remote rm 不会从服务器上删除远程仓库。它只是从本地仓库中删除远程文件及其引用。
MoyiTech
2023/02/27
1.9K0
Git秘籍: Git and Git Flow Cheat Sheet
GIT分支管理和常用命令
master 分支 不能往master 分支上提交代码,只能在该分支上进行代码合并操作,例如将其它分支的代码合并到 Master 分支上。 develop 分支 我们日常开发中的代码需要从 master 分支拉一条 develop 分支出来,该分支所有人都能访问,但一般情况下,我们也不会直接在该分支上提交代码,代码同样是从其它分支合并到 develop 分支上去。 feature 分支 当我们需要开发某个特性时,需要从 develop 分支拉出一条 feature 分支,例如 feature/update_mq 与 feature/update_netty,在这些分支上并行地开发具体特性。 release 分支 当特性开发完毕后,我们决定需要发布某个版本了,此时需要从 develop 分支上拉出一条 release 分支,例如 release-1.0.0,并将需要发布的特性从相关 feature 分支一同合并到 release 分支上,随后将针对 release 分支推送到测试环境,测试工程师在该分支上做功能测试,开发工程师在该分支上修改 bug。待测试工程师无法找到任何 bug 时,我们可将该 release 分支部署到预发环境,再次验证以后,均无任何 bug,此时可将 release 分支部署到生产环境。 tag 待上线完成后,将 release 分支上的代码同时合并到 develop 分支与 master 分支,并在 master 分支上打一个 tag,例如 v1.0.0。 hotfix 当生产环境发现 bug 时,我们需要从对应的 tag 上(例如 v1.0.0)拉出一条 hotfix 分支(例如 hotfix-1.0.1),并在该分支上做 bug 修复。待 bug 完全修复后,需将 hotfix 分支上的代码同时合并到 develop 分支与 master 分支。同时在master上打上tag,v1.0.1。 版本号 对于版本号我们也有要求,格式为:x.y.z,其中,x 用于有重大重构时才会升级,y 用于有新的特性发布时才会升级,z 用于修改了某个 bug 后才会升级。 个人分支 个人分支下可以建目录,例如: xiaoguai/dev1, xiaoguai/dev2
黄小怪
2018/12/11
1.3K1
GIT分支管理和常用命令
git 项目分支管理
2010年人家写的,(2010年我还不认识git)。原文在这http://nvie.com/posts/a-successful-git-branching-model/ 作者以自己的项目经验,画了一
技术蓝海
2018/04/26
6760
git 项目分支管理
相关推荐
你是如何玩Git分支模型的呢?
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档