前言
Git等版本控制工具最核心的使命是:
确保数据安全性和完整性。
提升团队协作效率。
但是如果分支管理不规范,这两点都可能得不到保障。
Git-Flow分支管理模型
自Linus Torvalds 2005年发布git以来,如今git早已一统江山,但git的分支管理却大相径庭,各有各的玩法。但其实2010年,就有一哥们(Vincent Driessen) 提出过一个git分支管理模型——Git-Flow,可以非常好的应用于发布频率稳定、需求明确的项目!
直接上图(上网一搜git-flow,可以发现这图其实都包浆了):

这个图就是Git-Flow的分支管理模型,从图上可以看到,涉及的分支有:
master:主分支,也是发布分支。所有提供给用户使用的正式版本,都得在这个分支上发布。develop:开发分支。代码最新。feature-*:功能分支。正在开发的新功能,未必确定上线版本。通常*的值对应issue key或者jira key。release-*:测试版本分支。提测分支,通常*的值对应一个版本号,表示是这个版本的内容。hotfix-*:紧急修复线上bug分支。通常*的值为当前线上版本号的修订版本+1(版本号规则:x.y.z,即z+1)。
其中,master和develop是长期固定的分支!其它都是从这两个分支创建出来的,最终要回到这两个分支,并被删除掉。
演练下
假设,现在有一个hello-world项目,目前发版频率稳定,每周三发版,每周四需求评审确定下一版本内容——即从需求池中拣选需求/缺陷归入到下一版本。
同时部署环境依然是常规的开发、测试、正式。
那么具体怎么按照Git-Flow的分支规范来践行呢?
比如现在线上版本是
2.0.2,接下来要上线的版本是2.1.0:
周四:需求评审后
需求评审结束,即确定了下个版本的内容,比如jira上的A~G 一共7个需求。此时相关开发人员应当先确定自己是否之前就完成了A~G的需求开发。例如张三早已完成了C的开发,那么应当已经存在分支 feature-c (无论这个分支在张三本地还是在仓库),此时张三应当将feature-c 合并到develop ,并删除feature-c 。然后团队开发人员都在 develop 上(团队成员少时),或者从develop拆分个人分支(团队成员人数多时) 进行A~G需求的开发。
develop应当集成开发环境,方便开发人员自测。
周四:下班前发现效率不错,已经做了2个需求了!准备先提测一波
总不能等A~G全开发好再提测,这样往往预留给测试人员的时间会非常紧。实际中,往往是覆盖式推进。于是,某个开发人员(往往可能是开发leader) 从develop checkout出了 release-2.1.0 。
release-*应当集成测试环境,以便测试人员测试。
如此,已经做好的A、B便可以由测试先行测一波了。
周五:线上环境出现bug,需要紧急修复
线上出问题了,需求紧急修复。开发人员应当从主分支master 创建一个 hotfix-2.0.3 (线上分支的修订号+1),并修复此缺陷,然后将 hotfix-2.0.3 合并到master 触发线上构建,然后再将 hotfix-2.0.3 合并到 develop ,最后记得删除。
如果此缺陷影响当前版本
2.1.0的测试,还需要合并到release-2.1.0。master分支记得打一个
2.0.3的tag!
次周一:已经发布到测试环境的A测出了问题
张三写完A需求没有自测,或者自己没测出问题,被测试测出来了。这时张三应当在release-2.1.0 修复A,推送触发构建到测试环境,并将release-2.1.0 合并到develop ,然后继续手头当前版本的其他需求。
张三手头上还在干的C、D应当继续在
develop上开发。
次周二:当前版本需求已经全部完成
应当将develop及时合并到release-2.1.0 ,并提交正式的提测申请。
此时,在下一个版本评审结束前,所有的开发工作都不会在develop 分支上进行。如果是2.1.0 测出来的问题,则直接在release-2.1.0 上进行修复并更新到测试环境;如果是需求池的其它需求,还不确定版本,则从develop新建feature-* 分支开发。
虽然明天就要发版,看似预留给测试的时间不多,但由于是覆盖式推进,
2.1.0版本中的很多需求测试可能都测完了。剩下的一天只需要系统性的回归下即可。
周三:测试通过,发版上线!
测试人员一旦完成测试,则开发人员应当将release-2.1.0 合并到master分支!同时也合并回develop 分支,并记得删掉此分支。
master分支可以集成正式环境,进行持续交付。master分支记得打一个
2.1.0的tag!
如此,便完成了一个版本迭代的整个过程!
运行良好。
有没有别的插曲?
Git-Flow这个机制目前看运行的很好,但如果发生以下问题呢:
1. 某个需求中途不上了
版本开发进行到周五,PM忽然说,A需求这个版本不上了!都开发完了,测试环境也都部署了。
首先,这种情况不能是常态!这只能说明PM对版本的把控能力不足。但实际中依然受不可控因素影响导致发生。这时如何解题?
如果A对应的提交尚未提测到
release-2.1.0,则直接在develop上git revert即可;如果已经提测,则直接在release-2.1.0上git revert即可。同时别忘了,将A的提交
cherry pick到feature-A,以备下次上线需要。
2. 某个需求feature-* 分支如何自测呢?
在上面的分支管理规范中,如果某个需求Z还没有排版本,但是开发完了想自测,是不能合并到develop的。
这种情况只能自己本地自测下了,如果涉及到数据库脚本的大量改动,可能还得有本地库才行。总之记住的原则就是以后的需求(非接下来版本的)不要贸然往
develop上合。
小结一下
Git怎么用,不是选择题,也不是判断题,没有标准解。如果项目很小,亦或是团队成员很少。就简简单单的 develop + master 也可以,甚至我个人的一些小项目,像小程序小应用,就只有一个master。
只能说,适合自己团队的就是最好的,如果当前团队中没有自己的规范,或者虽然有但仍然存在混乱等问题,可以尝试下Git-Flow这套玩法。
特别值得注意的是上面记录的Git-Flow和标准的Git-Flow还是有点区别的,主要体现在:
分支命名不同,上面提到的 -*,标准Git-Flow是/*,例如
release-2.1.0, 标准命名可能是release/2.1.0标准的Git-Flow 在
feature-*分支开发完应当直接合并develop,这可能更适合非业务系统,或者功能的上线次序,遵循的是先做先上。但是国内很多业务系统,团队管理模式下,可能出现需求池,排期,开发超前做等情况,因此标准的可能不太试用。
参考
A successful Git branching model —— 就是Git-Flow提出人(Vincent Driessen))发表的
介绍一个成功的 Git 分支模型 —— 上面的译文版