【实战分享】使用Git Flow的代码管理之道

747 阅读7分钟
原文链接: cloud.tencent.com

导言

本文将介绍一个被广泛使用的,基于git的项目管理工作流程git flow。git flow是git的一个扩展集,这里我们介绍当前最流行的AVH版本,AVH版本以Vincent Driessen提出的分支模型为基础,在已有的git flow上增加了更多的功能,同时重写了部分内置命令的实现,从而在提供高层次的库操作同时,对性能也有进一步的提升。

背景

从毕业之后,以一线后台程序员的身份,陆续几年工作到现在。前前后后使用过c/c++、java、python、nodejs和golang等多种语言,与此同时,使用的代码版本控制工具也有TFS、SVN和Git。而目前更多的,大家使用的都是Git作为版本控制工具,对于一般的项目(大中小型),当你不知道使用哪种版本控制工具时,Git永远都是最佳适合。当然,Git作为现代化的分布式版本管理工具,使一个程序员在自己开发代码时可以在很多地方做很多事情。然而,当我们放大项目和团队规模,随着在同一个项目内一起开发的人越多,每个人的commit习惯不同,在我们使用Git管理项目时,会很容易出现错乱和冲突。此时,一个统一的、规范的、特定的工作流程就很必要了。

最近的项目中,Leader推荐了一个基于Git的项目管理方式:Git-Flow。在2010年,Vincent Driessen提出了一个经典的git分支模型,有兴趣的同学可以去下文阅读:Vincent Driessen’s branching model。本文介绍的git flow就是以Vincent Driessen的分支模型,致力于通过git的分支和发布策略帮助开发者轻松地跟踪当前项目的功能开发、紧急修复、发布等。考虑到阅读本文的都已经具备基本的Git知识,我们直接来看看一个完整的git flow分支管理体系图示:

一个完整的git flow分支体系图

在网络上,有很多关于git flow的分支走向图,但是作者觉得最清晰、最全面的还是上面这幅。这幅图涵盖了本文的几乎所有内容,接下来的所有内容几乎都是契合着这张图来说明。

首先,由上图所示,显而易见地,在git flow版本控制管理中,主要存在着五个分支:master,release,develop,feature和hotfix,其中:

1. 长期分支

  • master:主分支,主要是用来存放稳定的、可随时上线的版本。master分支不允许直接进行代码commit,只可以接收分支的merge request(gitlab)或者pull request(github)。
  • develop:主开发分支,每次迭代都是主要在该分支上进行,当需要开发一个个新功能时,所有的feature分支都是从该分支切出去的。而 feature 分支的功能完成后,也都需要合并回來该分支。

2. 临时分支

  • release:发布分支,该分支上的代码将会被通过完整测试,并将用于下一次发布。通过单独的release分支进行测试,既可以保证在从develo切出release之后可以立即在develop上继续开发,从而实现开发与测试的并行,同时也避免了develop分支的开发代码污染道测试版本。
  • feature:功能开发分支,主要用于在一个迭代中,由develop分支切出来,用于开分不同功能开发。
  • hotfix: 紧急修复分支,主要用于修复线上bug,只会从master分支拉出,且在修复完毕bug后,需要同时合并到master分支和develop分支。

上述分支中,master和develop是两个长期存在的分支,伴随着整个项目的生存周期而存在着,而其他分支,将会随着每一个git flow任务的开始和结束而被创建和删除。

安装git glow

macOS

通过Homebrew:

$ brew install git-flow-avh

Linux

在ubuntu下,通过apt-get:

$ apt-get install git-flow

或者,通过源码安装:

$ wget --no-check-certificate -q https://raw.githubusercontent.com/petervanderdoes/gitflow-avh/develop/contrib/gitflow-installer.sh && sudo bash gitflow-installer.sh install stable; rm gitflow-installer.sh

Windows (Cygwin)

$ wget -q -O ---no-check-certificate https://raw.githubusercontent.com/petervanderdoes/gitflow/develop/contrib/gitflow-installer.sh

$ ./gitflow-installer.sh install state $ rm -rf gitflow gitflow-installer.sh

更过关于安装AVH版本的git flow,可以参考这个链接:git flow avh版本安装指引

初始化Git flow

$ git flow init [-d]

当在项目的根目录执行 “git flow init” 命令时,将会有一个交互式安装引导初始化操作。该操作主要是在分支上配置了一些命名规则。需要注意的是,尽管git flow允许使用自定义的名称,但是强烈建议使用默认的命名机制,并且一步一步地确定下去,或者直接使用-d参数(-d参数,表示接收所有默认的配置)。

$ git flow init -d
Initialized empty Git repository in /data/code/src/example_repo/.git/
Branch name for production releases: [master] 
Branch name for "next release" development: [develop] 

How to name your supporting branch prefixes?
Feature branches? [feature/] 
Release branches? [release/] 
Hotfix branches? [hotfix/] 

在项目初始,我们必定要将两个长期分支创建出来:master和develop。接下来,就让我们步入使用git flow的主要流程中来。

开发新功能(feature)

开始一次功能开发

敏捷是当前软件开发行业的一个主要模式,在一次迭代中,一般都是有着多个功能等待开发完成。在做新功能开发时,使用一个独立的分支是版本控制中最重要的规则之一。在多人开发同一个项目时,每个人在迭代初始领取任务之后,我们便可以进入到develop分支,并开始一次新功能的开发:

$ git flow feature start multiDownload

通过在develop分支上进行上述的操作,git flow 会创建并到换到一个名为feature/multiDownload的分支(前缀feature可以配置是否默认添加,建议保持加上),这样我们就可以在新的功能分支上直接进行工作了,对应的分支扭转图示如下:

开始一次新功能开发

完成一次功能开发

经过几晚加班后,终于完成了一个功能的开发,这时候,我们需要借用git flow来继续完成之前的新功能开发流程:

$ git flow feature finish multiDownload

通过上述命令,git flow会帮我们完成如下一系列的操作:

  1. 将我们的代码merge到主develop分支中去。
  2. 清理操作,删除这个feature分支,并且换到develop 分支。

上述过程对应的分支扭转图示如下:

完成一次新功能开发

当顺利的完成一个功能开发之后,我们便可以去进行下一个功能开发,如果当前迭代的功能全部开发完毕之后,我们则需要去进入完整的版本测试流程。

发布新版本(release)

当一次迭代开发完成,并充分的测试完成之后,我们便需要准备开始一次发布操作了,在git flow中,对于发布流程有着一套非常标准的操作:

开始一次发布流程

$ git flow release start 1.2.0

其中1.2.0是我们对release的分支名,通常来说,release分支我们都使用版本号来命名。通过上述操作,git flow会为我们创建并切换到一个新的分支:release/1.2.0。而在该分支上,我们将会进行代码编译,并发布到生产环境*,对应的图示流程如下:

开始一次发布流程

*注意:这个地方,作者建议在release分支上,对测试已经通过的代码进行直接编译并部署到生产环境。可能有的同学会疑问:为什么不使用master分支作为代码编译的分支?主要原因就是下文将提到的。

发现问题

当我们上线并回归测试时,可能会立即发现了问题,这时候还是需要在release分支上进行修改测试和继续发布操作。该步骤的出现概率一般都是比较低的,因为所有到了release分支的代码都是经过了大量的测试的。但是,诸如上生产后在回归测试的时候,可能立刻就直接发现了一个bug的现象还是会存在的。此时,正确的操作是在当前release分支上直接作出修改、提交和再发布,等到确保再无bug之后,再进入到git flow的完成发布流程。对应的分支扭转图示如下:

在release过程中修复问题

完成一次发布流程

当上线完毕,并回归测试确定没有bug之后, 我们需要完成本次release。请注意,这是一个较危险的操作:

$ git flow release finish 1.2.0

通过这个命令,git flow会帮我们完成如下一系列的操作:

  1. 拉取远程仓库,以确保目前是最新的版本。
  2. 将release 的内容同步merge到 “master” 和 “develop” 两个长期分支中。这是很重要的一个操作,可以保证生产环境代码(master分支)和主功能开发代码(develop分支)是一致的。
  3. release 提交会被标记上这个 release 的名字(也即是1.2.0)。
  4. 清理操作,这个release分支会被删除,并且切换到 develop分支。

到这儿,一个版本发布过程已经完成,对应的分支扭转图示如下,我们可以看到release分支的内容会被同时合并到master和develop分支:

完成一次发布流程

bug修复(hotfix)

当我们的产品在稳定的运行了一段时间后,可能在某天,因为某个不常见的场景,触发了一个严重的bug。这时候我们就需要走一个bug紧急修复的流程了。

开始一次紧急修复

在开始修复之前,如果正在develop上开发新迭代的功能,可以通过commit提交保存代码(如果不适合提交,也可以通过stash暂存)。请记住,所有的hotfix用于都是从master分支拉出,因此当git工作区干净之后,我们需要切换到master分支,然后开始一次紧急修复操作:

$ git flow hotfix start authFailed

通过上述操作,git flow会创建并切换到一个新的分支hotfix/authFailed,我们将在该分支上对bug进行修复、测试和上线*,对应的分支扭转图示如下:

开始一次紧急修复

*注意:与上文的release一样,当hotfix代码修复和测试完成之后,我们直接在hotfix分支上进行编译和发布。这样操作的原因,同样是为了避免上线回归后,发现并没有真正的修复问题(或是代入了新的问题),此时我们需要继续在hotfix分支上继续进行修改,并在最后回归通过后,再完成紧急修复流程。

完成一次紧急修复

当确认bug已经被修复,我们需要完成本次hotfix:

$ git flow hotfix finish authFailed

通过上述操作,git flow将会进行一个非常类似于发布一个 release 版本的过程:

  • 将代码同步merge到 master分支和develop分支中,同样,通过这步操作,可以在当前master分支上的bug被修复的同时,保证bug不会再次出现在下一个 release 中(当merge道develop中时,可能会出现冲突,此时可能需要手动merge解决)。
  • 这个 hotfix 程序将被标记起来以便于参考。
  • 清理操作,这个hotfix分支会被删除,并且切换到 develop分支。
完成一次紧急修复

在完成紧急修复之后,我们可以回到之前的develop分支继续功能开发,请注意,如果有进行stash暂存,不要忘了pop出来哦。

以上就是本文关于git flow的护照介绍内容,其实所有要说的内容,在第一张图上都可以看到踪迹。所以在阅读完成之后,强烈建议读者再回到本文的第一幅图,细细品味一下一个完整的git flow流程的分支管理模式。

附录

git flow 命令一览:

git flow 命令一览