一、概述
Git相比SVN的一个很强大的特性就是其分支,它可以花费很小的代价创建一个分支。那么我们应该在项目中如何使用它,提高整个团队的效率呢。
这篇文章就是对几种常用Git工作流程的一个学习笔记。
Git Flow
GitHub Flow
GitLab Flow
Git DMZ Flow
二、Git Flow
Git Flow可能是最早提出来的git工作流程,它的使用如下:
主要分支
Git Flow存在两条主要分支master
和develop
:
master
:稳定的发布分支,随时可发布develop
:开发分支,用于日常开发
每当master分支有新合并就意味着一个新的生产发布(production release)版本,所以可以使用自动化脚本自动部署master
分支的代码到生产服务器。
支持分支
除了两条主要分支外,平时开发过程中还需要其他的分支里支撑我们的工作,Git Flow里主要区分了一下临时性分支。这些分支只在某段时间存在,完成使命了就将被删除。
分支名称 | 来源分支 | 去向分支 | 命名约定 |
---|---|---|---|
功能(feature )分支 | devolop | devolop | 除master,devolop, release-*,hotfix-*外的任何名称 |
预发布(release )分支 | devolop | devolop 和master | release-* |
修复(hotfix )分支 | master | devolop 和master | hotfix-* |
NOTE:在使用合并(merge
)的时候,推荐使用--no-ff
,这样历史就很清楚在什么地方发生了合并,也方便撤销更改。
评价
Git Flow的优点就在于清楚、完善。但是,缺点也很明显,这个模式很复杂。要同时维护两个长期分支,而且有些支持分支需要和master
和devolop
分支都合并。
而且,这种流程对于持续交付的项目来说就不合适了。首先,项目可能每天都会构建,所以就没有必要区分master
和devolop
分支了,因为内容都差不多。其次,Git flow允许在release
分支上进行merge
操作(比如bugfix)。但是,这样就会造成devolop
分支交付时不一致。
三、GitHub Flow
GitHub flow的特点就是简单、可持续交付。它是GitHub使用的流程。
可以从图中看出来流程很简单:
- 任何时候,保证
master
分支都是稳定的、可部署的 - 当需要开发新功能或修复bug时,从
master
新建分支,分支名称必须具有描述性(如:功能名称或bug标题) - 在新的分支提交更改,然后和服务器同名的分支同步
- 发起一个Pull Request,当你需要帮助,反馈或分支开发完成的时候
- 当某人审查了你的代码,并通过了你的PR后,你就可以合并进
master
- 合并了以后就应该立即部署,然后就可以删掉该分支了
评价
Github flow很简单,而且很适合持续发布的项目。可以看出来它就是一个新建分支,开发分支,合并分支的一个流程。
但是,github flow的缺点也在于其太过简单了,很多问题(比如部署,环境,发布等)都不能很好的解决。所以,下面介绍第三种git工作流程——GitLab Flow。
四、GitLab Flow
Gitlab flow考虑了Git flow过于复杂和Github flow过于简单的问题,针对不同类型的项目使用不同的流程。它是GitLab网站推荐的流程。
持续交付的项目
对于本身不能控制发布的项目来说,Github flow就不是很好使。比如,苹果APP提交到AppStore之后,还需要审核后才能发布,那么对于审核期间提交的代码该如何呢。所以,使用Gitlab flow可以先merge
到pre-production
分支,然后再合并pre-production
分支到production
分支。
对于新功能开发和Bug修复,则采用上游优先(Upsteam First)原则。也就是说首先都是从master
分支拉出feature
分支或bugfix
分支,然后开发完成后,再向master
分支发起merge request(也就是Pull Request)合并进master
分支,但是先不删除该分支。当master
准备好(如果你遵循continuous delivery的话,master
分支就应该准备好)之后,然后再把该分支合并进其他分支。除非特殊情况才允许跳过master
分支,直接合并到pre-production
或production
分支。
版本发布的项目
对于一段时候需要产生一个稳定版本的项目,Gitlab flow也是采用上游优先的原则。当需要发布的时候就从master
分支拉出一条分支发布。如果需要bugfix,则首先还是在master
分支修改该bug,然后release
分支再从master
分支cherry-pick修复后的代码到自己的分支。这样就避免了release
分支修复的bug再master
分支中重复出现。而且,版本的命名参照Semantic Versioning来命名。
评价
GitLab Flow对于两种项目类型都能很好的支持,不像Github flow过于简单,也不至于像Git flow过于复杂。所以,可以说是一种很好用的git工作流程。
五、Git DMZ Flow
Git DMZ Flow是根据以下的原则设计出来的:
- 两个开发不同功能的开发者,必须不能被互相阻断
- 一个开发者应该能够基于另一个开发者的工作派生出自己的工作,而不需要等待第三方
- 两个开发者能够开发相关联功能或同一功能,而不会被其他人干扰或被干扰
- 开发人员必须能够同时开发不同功能,或者在一个功能完成时能够毫不延迟的开始下一个功能的开发
- 合并进
master
的代码必须经过代码审查 - 代码审查必须成为每个开发者每天的例行公事
- 针对
master
的持续集成必须保证master
保持稳定,如果master
不能保持稳定,就会干扰其他人的开发 - 这种工作流程必须支持不同规模的团队,以及具有任意分支数量的项目
整个原则最强调的两点就是:互不干扰和协作。所以,这是个强调高效流程原则。Git DMZ flow就是基于这样一个原则设计的。
介绍
前面介绍的三种工作流程,都是在支持分支上开发完了以后合并进主要开发分支(Git flow的devolop
,Github flow和Gitlab flow的master
分支)。我们能够保证每个分支在合并进主开发分支前都经过严格的验证和代码审查,可以构建通过。但是,当多个分支短时间内同时合并的时候,就不能保证合并后的主开发分支能够通过构建了。因为,分支各自运行可能都没问题,但是合并在一起后可能就会相互影响,导致构建失败。
如果直接在master
分支上合并,那么出问题以后,我们只能等到问题解决后才能开始新的工作,这就违背了上面原则提到的高效和互不干扰的原则。所以,Git DMZ flow建立了一条dmz
分支,专门用于分支合并。
DMZ分支
DMZ flow仍然有一条master
分支,而且,所有的功能分支和bugfix分支都应该基于master
分支来建立。因为,master
分支是一直保持稳定和可构建的分支状态。
dmz
分支则是为了合并而存在的,所以的pull request都应该向dmz
分支发起,而不是master
分支。当dmz
分支有合并时,CI服务器(持续集成服务器)就对dmz
分支的HEAD
进行完全构建。只有当构建成功后才由服务器自动合并进master
分支(使用快速合并)。
评价
DMZ flow因为有了dmz
分支,开发者可以不用花任何等待的时间就可以立即开始下一个功能的开发。可以说Git DMZ flow就是高效的象征,所以,如果项目追求快速开发的话,可以考虑使用DMZ flow。
六、总结
以上介绍了4中不同的git工作流程,不同的流程有其适用的场合。所以,不存在完美的流程,只有适合的。根据自己项目的具体的情况,选择合适的流程,或者自己设计一种流程可能才是最好的流程吧。