自从 Linux
之父Linus Torvalds
对当时的版本控制工具感到不满,亲自动手创造了 Git
以来,Git
已经逐渐在版本控制领域占据了主导地位。不论你的代码仓库托管在 GitHub
还是 GitLab
,不论你用的是 SourceTree
、GitKraken
这样的图形界面,还是喜欢直接敲 Git
命令,这些都没问题。因为 Git
带来的便捷性和高效性,我们已经越来越离不开它了。
然而,随着项目规模的增长和协作人数的增加,有些人发现 Git
用起来似乎越来越复杂:有时候合并时会遗漏文件,有时明明删掉的文件又重新出现,甚至每次合并都要解决几十上百个冲突。这时,你可能会怀疑 Git
的能力,心里嘀咕:“这 Git
压根儿就驾驭不了咱们这么庞大的项目。“
幸好,这个世界上只要有新的好工具,就会有一群懒惰的工程师开始想方设法地让自己的生活好过一点。Vincent Driessen 就是这种人,于是他根据自己的经验,将工作中经常会遇到的场景逐一整理,根据 git 的特性,制定了一套工作规范,也就是本文的主角:Git Flow
。
GitFlow
是一种 Git
工作流,这个工作流程围绕着项目的发布(release
)定义了一个严格的如何建立分支的模型。它是团队成员遵守的一种代码管理方案 。
Git
建分支是非常容易的,我们可以任意建立分支,对任意分支再分支,分支开发完后再合并。 比较推荐、也比较常见的做法是功能(特性)驱动(Feature Driven
)的建立分支法(Feature Branch Workflow
)。 简而言之,就是每一个功能(feature
)的开发并不直接在主干上开发,而是在单独的分支
上开发,分支开发完毕后再合并到主干上。
这样做的好处是: 1. 还处于半成品状态的功能不会影响到主干
。 2. 各开发人员之间在自己的功能分支上进行开发,互不干扰
。 3. 主干永远处于可编译、可运行的状态。GitFlow
则在这个基础上更进一步,规定了如何建立、合并分支,如何发布,如何维护历史版本等工作流程。
上号!直接开始
简单理解版本:
刚开始的时候,我们有个master
分支,我们要基于master
来创建develop
master
master
分支上存放的是最稳定的版本
,并且该分支的代码是随时可以让用户使用的代码
,就是非常非常稳定的代码。当一个版本开发完成之后,交付给客户的时候,master
上面的代码也要被更新。同时,每次更新都要打上相应的tag
。
任何人不允许在master
上进行代码的直接push
提交,只接受其他分支合入。原则上master
分支必须是release
的分支合过来的代码。
来源只能是:hotfix
和release
分支。不能是其他分支。
master
一定是经过多轮测试,但是不能保证完全没有bug
,所以引入hotfix
分支,来修复未知bug
develop
develop
是主开发分支,这个分支上被合并的代码始终是下一个版本需要加入的feature
。这个分支可以合并一些feature
。当要release
的时候,就从这个分支上进行创建release
分支。
合并到develop
分支上的必须保证功能完整,不影响develop
分支的正常运行。
feature
feature
分支又叫功能分支,一般命名方法feature/xxx
,用来开发版本或者未来要发布新的功能或者探索新功能。(feature
分支功能要保证里面的commit
的粒度要非常细
,避免和主分支脱节严重,应该大功能切成一个一个小功能来merge
,而不是一次merge
一个大的)
Release
这个分支又叫预发布分支,一般命名为 release/1.1.x
这个分支转为发布做准备。允许小量级的bug
修复。
release
分支只能从develop
分支拉过来,用来修复一些bug
。(不做feature
相关的开发)
hotfix
hotfix
叫热修复分支,一般命名为hotfix/4.1.3
为固定某个版本进行修复,当master
上遇到严重问题需要修复的时候,就要从master
上指定tag
拉取。这样做就是为了隔离feature
开发和bug
修复。
hotfix
只能从master
上拉去,测试通过之后合并会master
和develop
详细版:
我们省去理论介绍的部分,直接从工作中一个平凡无奇的早晨开始,大家跟着叙述场景,一起看看 Git Flow
到底怎么帮助我们梳理工作流程,节省时间的。
假设,你们已经有了master
和 develop
两个常驻型分支,其他分支都没有。早上你泡好咖啡,从你的座位上坐下,决定好今天要为这个项目加上一个发 email
的新功能,这时,你应该创建一个新的特性分支,并命名为add_email
。
黄色为
develop
分支,蓝色为master
分支
图中绿色的点代表了release分支短暂的一生。一旦开启release分支,就进入了发布前的最终测试阶段。
也有人将release
分支仅视为进入master
之前的缓冲区
,所有的最终测试都是针对master
进行的,一旦发现问题就新开分支修复。
这两种做法各有优缺点,我认为都挺好,但有一条必须严格遵守
-release
分支只能修 bug
,不能添加新功能。
一旦开了release
分支,就只能修复 bug
,不能再加新功能。 这一点非常重要,因此重复三遍。实践中,总有人喜欢在 bug
修复中夹带新功能,但要知道,此时往往缺乏全面回归测试的支持。这相当于在即将发布的版本中,悄悄植入未经充分验证的新功能,等同于埋下了随时可能爆炸的炸弹。
一旦在正式环境中发现问题需要修复,这时就需要使用hotfix
分支了。
黄色为
develop
分支,蓝色为master
分支
图中的红色圆圈就是hotfix
,它从master
分支切出,结束时同样要合并到master
,并顺便同步到develop
,流程和release
分支类似。
实际上,我们在处理hotfix
时,也要像对待release
一样: 开分支的同时就要确定版本号,只能修复 bug,不能夹带新功能
。 理由很简单,hotfix
和release
跟正式环境运行的代码版本基本是一样的,因此对它们的谨慎程度也应该相同。而且由于hotfix
通常紧急,更难以进行全面的回归测试(即使有回归测试,也不能完全保证无误)。因此,为了避免更大的损失,一定要慎之又慎
测试完毕,hotfix
,重新上线,同时修复了develop
,世界又回到了最初简单的状态,只剩下develop
和master
两个分支。
我认为,越是庞大的产品,越是要有简单的架构;越是复杂的工作,越是要用简单的方法处理。有了 gitflow
,你可以有一套简单的标准去套用工作上的场景。因为这套工作流程比较简单,所以你并不应该等到事情变得复杂才来解决。请容我换个方式再讲一次:
gitflow
的目的是要用简单的流程解决工作上的问题,所以不要把问题放到很复杂了才想要来解决。
原则切记:
feature
分支的生命周期不宜过长,最多最多不要超过一个迭代周期- 如果一个
feature
分支包含的功能太多太复杂,开发周期太长,应该拆成几个小的feature
- 发版前必须切出
release
分支,预上线的测试版本一定要和实际上线的版本一致 release
分支上只能做bug
修复。hotfix
和release
分支开启时即要决定版本号,且同样只准修复bug
,不可加入新功能。- 经常存在的分支只有两个:
develop
与master