团队如何选择合适的Git分支策略

简介: 选择合适的分支模型Git代码分支管理模型各具特点,流程只是一个辅助工具,没有最好,只有最合适。• 如果开发团队规模较小又比较分散,产品发布周期较短(例如:初创公司,或者开发的是一个网站或 Web 应用程序,在一天内可能需要发布多个版本),可以选择GitHub flow或者GitLab flow;• 如果开发团队规模较大,产品发布周期较长(例如:团队超过20人,采用了月度或季度发布周期,并且由一个团队负责并行开发多个项目),可以选择Git flow,发布周期较短可以选择TBD flow;• 如果开发团队规模大,产品发布周期长,同时对敏捷的要求比较高,可以考虑TBD++ flow。每个组织

现代软件开发过程中要实现高效的团队协作,需要使用代码分支管理工具实现代码的共享、追溯、回滚及维护等功能。目前流行的代码管理工具,包括CVS,SVN,Git,Mercurial等。


相比CVS和SVN的集中管理,Git具有非常明显的优势,例如:去中心化的代码管理方式减少了开发者对中心服务器的依赖,每个成员在本地都有一个完整的代码库,在不联网的情况下也能提交代码;不同于SVN中的每个分支具有独立的代码,Git中的每一个分支只是指向当前版本的一个指针,Git的分支策略使创建和合并分支变得快捷灵活


从百度指数,也可以看到Git的优势被越来越多的人所认可。


Git的优势

  • Git 可以在本地进行提交以支持离线工作;
  • Git 可以在本地创建分支并且没有命名空间冲突的问题;
  • Git 可以让提交通过 Pull Request 的方式进行,不需要所有的开发者都有主仓库的写权限;
  • Git 在优化性能时选择了合并分支作为主要的性能衡量指标,将合并分支变成了成本非常低的操作以鼓励分支的使用;
  • Git 通过 SHA-1 哈希来保证仓库中数据的可靠性,通过 SHA-1 就可以对数据进行校验,抵御了来自攻击者的恶意篡改;


版本管理的挑战

Git作为分布式的代码管理工具,越来越多的团队开始使用它并逐步替代集中式的SVN 或 TFVC,同时也面临新的问题和挑战,如下:

  1. 如何开始一个Feature的开发,而不影响别的Feature?
  2. 由于很容易创建新分支,分支多了如何管理,时间久了,如何知道每个分支是干什么的?
  3. 哪些分支已经合并回了主干?
  4. 如何进行Release的管理?开始一个Release的时候如何冻结Feature, 如何在Prepare Release的时候,开发人员可以继续开发新的功能?
  5. 线上代码出Bug了,如何快速修复?而且修复的代码要包含到开发人员的分支以及下一个Release?


大部分开发人员现在使用Git就只是用三个甚至两个分支,一个是Master, 一个是Develop, 还有一个是基于Develop打得各种分支。这个在小项目规模的时候还勉强可以支撑,因为很多人做项目就只有一个Release, 但是人员一多,而且项目周期一长就会出现各种问题。


Git代码分支模型

在使用Git管理代码以及多人协作的开发模式下,一个团队甚至一个公司对Git的使用有统一规范的工作流程尤为重要。

开发团队遵循统一的规则执行功能开发,问题修复,分支合并,版本迭代及发布等操作,可以使团队合作变得平滑顺畅,项目有序向前推进,我们把组织内这样的工作流程(workflow)称为Git代码分支管理模型


主流的git代码分支管理模型:

  • Git flow
  • GitHub flow
  • GitLab flow
  • TBD flow


1. Git flow

Git flow存在两个长期的独立分支:主分支master和开发分支develop,

  • 主分支: 用于版本发布,主分支的每个版本都是质量稳定和功能齐全的发布版。
  • 开发分支: 用于日常开发工作,存放最新的开发版代码。当开发分支的代码达到稳定状态并可以发布版本时,代码需要被合并到 master 分支,然后标记上对应的版本标签(tag)。


如果需要开发新的功能或者解决代码中的问题,则创建辅助分支来解决问题,辅助分支常用于:

  • 功能开发(Feature),
  • 版本发布(Release),
  • 问题修复(Hotfix),

在辅助分支上的工作完成后,辅助分支将被删除。


Feature分支

目的是开发新模块或新功能以满足客户需求,从develop分支创建,开发结束后只需要合并回develop分支,并不需要合并回master主分支。


Release分支

是用于准备发布的版本分支,从develop分支创建,创建时已经包含了发布所需要的所有功能,所以在这个分支上不再开发新功能,仅对这个预发布版本进行修复问题,创建文档及其他与发布相关的工作,一切就绪后将Release分支合并回master主分支并打上相应的版本号标签(Tag),同时也合并回develop分支。

创建单独的Release分支可以避免在不同发布版本上的工作互相受影响,例如团队A准备发布版本1.0的同时,团队B正在进行版本1.1的功能开发,二者相互独立,不会互相影响。


Hotfix分支

通常用于紧急修复当前发布的版本中出现的严重问题,从发布版本的标签或master主分支创建,问题修复后合并回master主分支并打上新的版本号标签(Tag),同时也合并回develop分支或者正在进行中的Release分支。

创建单独的Hotfix分支可以避免打断正在进行中的各项开发工作,客户也不需要等到下一个发布周期才能拿到修复。


优点&缺点

Git flow需要同时维护两个甚至更多分支,Hotfix分支从master创建,Release和Feature分支从develop创建,工作完成后又需要将代码合并回 develop 和 master。


在实际应用中,很多开发者会忘记合并回 develop 或者 master,并且各辅助分支之间互相独立,如果从master上pull代码不够及时,一方面可能造成某个分支长期使用已经过时或者错误的代码,另一方面如果与master相隔较远,合并分支时可能会有大量代码冲突,往往需要花费很多时间来消除代码冲突,并且非常容易出错,影响项目的持续集成。


Git flow的优点在于流程清晰,分支管理严格,适用于发布周期比较长的“版本发布”,发布周期可能是几周,几个月,甚至更长时间

由于保持两个长期分支同步的开销较大,所以Git flow并不适用于快速的“持续发布”,ThoughtWorks还专门将Git flow列为不被推荐的技术,建议彻底停止使用。


综合考虑了开发、测试、新功能开发、临时需求、热修复,理想很丰满,现实很骨干,这一套运行起来实在是太复杂了

2. GitHub flow


GitHub flow是由Scott Chacon于2011年提出的代码分支管理模型,这是GitHub官方推荐的开发流程,以快速部署为目标,目前大部分开源项目都遵循这一流程。


Github flow最大的特点是只有一个长期分支,即主分支master,且主分支始终保持可发布状态。

从master上创建新分支进行功能开发、问题修复等,这些分支通过pull request将代码合并到master。为了保证主分支的代码质量,master的权限只开放给一部分人。

Pull request是请求别人pull你的代码库(repository),也就是把开发分支的代码经过代码评审并通过测试后,让有权限的管理员合并回master。


不过在实际情况中,代码评审不可能检查出提交的代码中的所有问题,所以对于每次提交的代码进行自动化测试,

主分支代码的自动化部署尤其重要,自动化测试能在产品部署前及时发现一部分问题,如果产品部署之后发现严重问题,自动化部署可以在最短时间内把产品回滚到上一个版本。


优点&缺点

Github flow的优点在于流程简单灵活,不需要考虑及管理太多的分支,适用于需要快速集成及“持续发布”的项目,这类项目可能需要每天发布一个版本,甚至一天发布多个版本。但是对于应用场景比较复杂的情况,例如:多个环境下的产品部署,多个版本的发布或问题修复,只有一个master便会显得力不从心。


github flow这种方式,要保证高质量,对于贡献者的素质要求很高,换句话说,如果代码贡献者素质不那么高,质量就无法得到保证。


3. Gitlab flow

GitLab flow是由GitLab 的 CEO Sytse Sijbrandij 于 2014 年正式发布的代码分支管理模型,属于GitHub flow的演进版本。


与GitHub相同之处是也存在一个长期主分支master,从master上创建新分支进行功能开发、问题修复等,结束后合并回master。

与GitHub不同之处是GitLab flow又考虑多环境部署等现实因素,增加production产品分支用于在不同的环境下部署产品,或者从master的稳定版本创建release发布分支用于发布软件。


如果在产品分支或者发布分支发现问题,就从对应版本分支创建修复分支,修复完成之后,GitLab flow遵循 “上游优先” 的合并策略,也就是将代码先合并到 master,再合并到下游的production或release分支。


和Github flow类似,master的修改权限只开放给部分人,开发分支的工作完成后,代码通过merge request(类似于GitHub flow中的pull request)请求有权限的管理员把代码合并(merge)回主分支


4. TBD flow


TBD (Trunk-based Development) flow是由Paul Hammant于2013年提出的模型。


TBD flow最大的特点是所有开发都基于主干trunk,不再有长期的开发分支,要求所有的提交尽快回到主干,这样可以共享最新的代码,并且能尽可能地减少合并冲突。如果需要发布版本,可以基于trunk直接生成新的分支用于发布。


TBD flow没有pull或者push request,要求开发人员尽快把代码提交到主干分支,但是TBD flow缺乏严格的流程来保证每一份提交代码的质量,如果一些项目开发人员众多且水平不一,同时工作在主分支上可能会在产品发布时才发现不可预知的问题,


所以TBD flow更适用于需要快速迭代的产品,如果在主干分支上发现问题,可以快速进行修复再合并回主干分支。


5. TBD++ flow

TBD++ flow是Arrus公司软件研发部门从2015年开始一直沿用的Git分支管理模型,产品项目的客户主要是电信级服务运营商,每个国家或地区的需求在主要功能上一致,但在客户定制化方面又存在不少差异,同时项目开发周期较长,整个周期一般在3个月到2年之间,软件产品在项目前期需要有快速的迭代,在项目后期需要有稳定的发布版本。(PS: 前面这些因素是选择该模型的重要考量因素,产品型开发,主线功能大体一致,维护客户多,发布周期固定且稍长


TBD++ flow以敏捷开发为核心,同时吸收了以上几个主流模型的优点,主要特点如下

1. 基于功能的主分支

只存在一个长期的独立分支,即主分支master,主分支上功能齐全,通过自动测试保证基本功能运行正常,因为自动测试覆盖不全面或者手动测试不及时,所以无法保证主分支的每个版本都是质量稳定的发布版,但是可以根据功能的完成程度直接从主分支上创建迭代版本用于针对不同客户或者不同时期的功能演示。基于master开发功能或者修复问题需要用到以下两个辅助分支:

  • Feature分支:为了开发新模块或新功能以满足客户需求,从主分支上创建Feature分支,但是并不要求Feature分支上所有的提交尽快回到主分支,开发完成并且通过代码评审及功能测试后才能合并回master主分支。为了共用主分支上的最新代码以及避免合并代码时解决代码冲突引起的额外开销,在功能开发过程中Feature分支需要始终与master保持同步。
  • Bugfix分支:基于主分支创建Bugfix分支修复主分支上发现的问题,修复完成并且通过代码评审后代码合并回master主分支。


基于主分支的Feature分支和Bugfix分支完成后,开发者直接将代码合并回主分支master,不需要像GitLab或GitHub那样依赖于少数几个有权限的管理员,这是因为如果一个项目中开发人员比较多的话,管理员没办法做到对每部分代码都熟悉或掌握,所以代码质量交由代码评审和功能测试来掌控,合并代码回主分支的操作由开发者自己完成。


主分支上的新代码有时候可能因为评审或测试不全面而带来新问题,例如破坏其他功能模块,甚至影响整体功能。为了能尽早发现问题,主分支上的每次提交都会触发系统级自动化测试,并且周期性地对主分支进行人工测试。一旦发现问题,主分支的专职配置管理员(Software Configuration Manager,SCM)将根据问题的严重性和紧迫性决定是否需要直接回退引起问题的提交,或者基于master创建bugfix分支进行问题修复。

2. 基于发布的Release分支

Release分支负责对外发布软件产品,每个Release分支也会配备专职版本配置管理员SCM,SCM具有对Release分支的最高管理权限。当master上已经包含了某个发布所需要的所有功能,并且没有已知的严重问题,此时由SCM从主分支上创建Release分支准备系统集成测试,和Git flow相同,在此分支上不再进行新功能的开发,仅在这个分支上进行修复问题,创建文档,客户参数配置及其他与发布相关的工作,这些代码同时也需要合并回master以确保主分支功能的完整性。


在每个Release分支正式发布前可能还需要将主分支上的一部分关键问题的修复选择性地同步(Cherry-pick)到Release分支,这个操作也是由SCM完成。

Release分支上的工作一切就绪并通过系统集成测试后,SCM在Release分支上打上相应的版本号标签(Tag)进行发布,这点和Git flow在主分支上进行发布不同。


软件产品发布之后,如果发现紧急或者严重的问题,此时需要基于版本发布时的Release分支标签创建Hotfix分支来修复此类问题,问题修复后合并回该Release分支以及其他同样需要此修复的Release分支,并打上新的版本号标签(Tag)用于发布,同时代码也需要合并回master以确保主分支的健壮性。

选择合适的分支模型

Git代码分支管理模型各具特点,流程只是一个辅助工具,没有最好,只有最合适。

  • 如果开发团队规模较小又比较分散,产品发布周期较短(例如:初创公司,或者开发的是一个网站或 Web 应用程序,在一天内可能需要发布多个版本),可以选择GitHub flow或者GitLab flow;
  • 如果开发团队规模较大,产品发布周期较长(例如:团队超过20人,采用了月度或季度发布周期,并且由一个团队负责并行开发多个项目),可以选择Git flow,发布周期较短可以选择TBD flow;
  • 如果开发团队规模大,产品发布周期长,同时对敏捷的要求比较高,可以考虑TBD++ flow。每个组织根据产品、项目、人员的特点找到最合适的模型才是共同的目标。对于某个长期产品的开发和客户版本维护场景,这种分支是笔者比较推荐的。


以上这些分支策略,仅仅是作为大家实践的参考,不同的开发模式和发布节奏,以及团队的人员水平,基础设施水平等都是选择分支模型的参考因素。


参考

相关文章
|
29天前
|
开发工具 git
git学习四:常用命令总结,包括创建基本命令,分支操作,合并命令,压缩命令,回溯历史命令,拉取命令
这篇文章是关于Git常用命令的总结,包括初始化配置、基本提交、分支操作、合并、压缩历史、推送和拉取远程仓库等操作的详细说明。
98 1
git学习四:常用命令总结,包括创建基本命令,分支操作,合并命令,压缩命令,回溯历史命令,拉取命令
|
1月前
|
开发工具 git 开发者
关于git 解决分支冲突问题(具体操作,包含截图,教你一步一步解决冲突问题)
本文通过具体操作和截图,详细讲解了如何在Git中解决分支冲突问题,包括如何识别冲突、手动解决冲突代码、提交合并后的代码,以及推送到远程分支。
271 3
关于git 解决分支冲突问题(具体操作,包含截图,教你一步一步解决冲突问题)
|
2月前
|
缓存 开发工具 git
Git创建分支以及合并分支
在Git中,创建分支使用`git branch [branch_name]`,切换分支使用`git checkout [branch_name]`。修改文件后,通过`git add [file]`添加到暂存区,然后`git commit`提交到本地仓库。如果是新建分支的第一次推送,使用`git push origin [branch_name]`推送到远程仓库,之后可以简化为`git push`。合并分支时,使用`git merge [branch_name]`将指定分支的更改合并到当前分支。
52 2
Git创建分支以及合并分支
|
30天前
|
开发工具 git
Git分支使用总结
Git分支使用总结
32 1
|
2月前
|
存储 Linux 开发工具
Git基础命令,分支,标签的使用【快速入门Git】
本文详细介绍了Git版本控制系统的基础概念和常用命令,包括工作区、暂存区和版本库的区别,文件状态的变化,以及如何进行文件的添加、提交、查看状态、重命名、删除、查看提交历史、远程仓库操作和分支管理,还涉及了Git标签的创建和删除,旨在帮助读者快速入门Git。
Git基础命令,分支,标签的使用【快速入门Git】
|
前端开发 开发工具 git
一入前端深似海,从此红尘是路人系列第十一弹之如何合理利用Git进行团队协作(二)
上篇我就Git协议讲了两大点,Git的起步,Git的基础操作,其中详细的小伙伴可以先去阅读我上一篇文章https://my.oschina.net/qiangdada/blog/800093(一入前端深似海,从此红尘是路人系列第十弹之如何合理利用Git进行团队协作(一))。
1737 0
|
3月前
|
存储 开发工具 git
|
6天前
|
缓存 Java Shell
[Git]入门及其常用命令
本文介绍了 Git 的基本概念和常用命令,包括配置、分支管理、日志查看、版本回退等。特别讲解了如何部分拉取代码、暂存代码、删除日志等特殊需求的操作。通过实例和图解,帮助读者更好地理解和使用 Git。文章强调了 Git 的细节和注意事项,适合初学者和有一定基础的开发者参考。
21 1
[Git]入门及其常用命令
|
3月前
|
开发工具 git
【GIT 第二篇章】GIT常用命令
Git常用命令涵盖初始化、状态管理、提交、分支处理、远程操作等关键流程。`git init`启动本地仓库,`git clone`下载远程仓库。通过`git status`和`git diff`检查工作状态与差异。利用`git add`暂存文件,`git commit`保存更改。借助`git branch`、`git checkout`、`git merge`和`git rebase`管理分支。使用`git fetch`、`git pull`和`git push`同步远程仓库。通过`git reset`、`git revert`和`git checkout`实现版本回退。
65 0
|
10天前
|
开发工具 git 开发者

相关实验场景

更多