# Git开发流程规范

版本：v1.0

时间：2019-01-30

[TOC]

## 概述

### Git

Git是一个版本控制系统，与SVN，CVS这些集中式版本控制系统（Centralized Version Control System）不同，Git是一个分布式版本控制系统（Distributed Version Control System），而且可以说Git是目前世界上最先进的分布式版本控制系统。

Git与SVN，CVS相比较，其显著特点为：

- 快速

- 设计简单

- 支持上万并行开发的非线性开发模式

- 完全分布式

- 有能力高效管理超大规模项目

- 无集中式单点问题可快速恢复

至于GIt为什么具有如此神奇的能力，以及GIt具体如何使用，请参考resources目录下的《progit_v2.1.16》文档

### Gitlab

Gitlab与GitHub一样，是一个用于仓库管理系统的项目，使用Git作为代码管理工具，并在此基础上搭建起来的web服务。区别在于Gitlab是完全免费的开源项目，而且可以根据需要在内网自行搭建，是企业内部进行版本管理的首选应用工具。

### Gitlab flow

基于Git的分支管理技术，可以演化出很多涉及：版本开发，版本测试，版本迭代，版本发布和Bug修复的工作流，工作流不涉及任何命令，因为它就是一个规则，完全由开发者定义并遵守，其中比较流行的最佳实践包括：

- Git Flow
- Github Flow
- Gitlab Flow
- Trunk-Based Development

这些基于Git的工作流最佳实践无所谓好坏，只有是否满足和适合当前的场景需要。

产品研发类项目与互联网在线项目和SaaS应用服务项目在需求迭代，开发实效，功能发布等方面存在区别，例如：

- 开发周期相对较长，中间一般会有里程碑
- 产品需求相对固定，不存在频繁变更
- 单一功能需要开发在时间上要求不十分紧急
- 业务模块进行分模块开发，人员之间的业务交叠不大
- 产品一般在功能全部具备时才发布现场使用

对于产品研发类项目采用Github Flow这种面向开源项目的工作流太过简单，Trunk-Based Development这种非feature分支开发方式不利于任务分配和跟踪，Git Flow这种面向版本的流程虽然满足需要但是太过复杂。而且个人以为这些流程大多都是面向互联网项目的最佳实践。综合分析最终选择Gitlab flow的releaseion branch with GitLab flow方式，并结合任务管理，持续集成形成满足我们当前需要的产品研发工作流。

GitLab工作流十分年轻，2014 年 9月 29 正式发布。由于出现比Git FLow和GitHub FLow晚，因此它集百家之长，补百家之短。GitLab 既支持 Git Flow 的分支策略，也有类似 GitHub Flow 的 Pull Request和 issue tracking，这些对于产品研发类项目都是极好的能力

## 开发流程

### 流程视图

 以下为完整的git开发流程![](https://i.loli.net/2019/02/07/5c5c32ce8cda2.jpg)

1.  在gitlab创建仓库，创建master分支和release分支，master分支初始代码为开发需要的框架代码
2.  需求分解，获得feature，粒度3天，使用gitlab的issue对feature进行管理，标记feature标签，命名以Feature_简单描述
3.  feature开发时从master分支拉feature分支进行开发，开发完成后，本地完成测试，确保代码无误后，提交Merge request
4.  在进行代码审核通过后，feature分支合并到master分支，触发持续集成（自动编译，代码静态检查，单元测试），成功后发布到持续集成开发环境，删除feature分支
5.  创建每日集成，每日定时将master分支代码进行自动化集成，完成后发布到每日集成开发环境
6.  待一个里程碑feature开发完成后，发起里程碑计划，手动触发集成部署到测试环境
7.  测试环境产生的bug录入fixbug issue在issue进行管理，开发人员从master分支拉取fixbug分支进行bug修复（过程类似feature branch）
8.  当里程碑测试完成后，release分支与master分支进行merge，在release上产生里程碑版本，并tag为milestone_vx.x
9.  以上过程随里程碑不断迭代推进，直到产品全部完成， release上将产生最后的产品发布版本

### 基本准则

1. **使用Feature分支，不直接提交到Master分支**

```
当开发一个新的功能或者修改bug时，应该创建一个分支进行开发或修复，完成后提交Merge Request，而不要直接基于Master分支进行任何开发。
```

2. **测试所有的提交，不仅仅是Master分支上的提交，在所有的提交上运行所有的测试**

```
持续集成如果仅仅是测试那些被合并到master的提交是不够的，对于master应该总是保持测试结果均为绿色，也就是说持续集成是应该是重新做一次完整的自动化测试，包括之前已提交的模块。
```

3. **及早提交Feature分支到Master分支，并且在合并到Master分支前执行代码评审**

```
为了发挥持续集成的作用“尽早集成，尽早发现和解决问题”，Feature分支开发完成应该尽早的提交Merge Request,理论上一个Feature的开发时间尽量不要超过3天，如果超过，拆分Feature,千万不要在一周结束的时候才提交所有内容。
提交Merge Request后，尽可能的落地代码走查和评审，特别是对于经验尚浅的开发人员，提交Merge Request时必须cc开发经理和相关开发人员完成代码走查和评审
```

4. **基于Master分支进行持续集成，并实现开发环境的自动化部署**

```
在Master分支部署持续集成流程，当Feature分支Merge到Master分支时进行自动化构建，单元测试和其他代码检查，通过后自动将代码发布到开发环境（实时更新）。另外，考虑到变更如果频繁会影响基于开发环境的调试，建议创建一个每日定时构建的开发环境，同样自动化部署
```

5. **基于Milestone创建里程碑版本，手动创建里程碑测试环境**

```
产品研发的里程碑要创建里程碑版本，以确保在一个阶段结束时，当前软件版本可用，测试在此环节介入，手动从Master分支部署测试环境进行集成测试，注意里程碑版本不对外发布，只属于研发内部流程中
```

6. **依赖tags版本进行发布**

```
Milestone里程碑版本测试完成后，将release分支与Master分支Merge，并通过tag（Milestone_vX.X），基于release分支发布里程碑版本，release分支就是里程碑版本分支，永远记录当前最新里程碑版本的内容，记住不要直接对其进行任何操作，除了Merge,tag
```

7. **绝不以重置方式提交变更**

```
禁止使用 git rebase, 代码应该纯净，修改历史应该真实。
```

8. **每个人都应该从Master分支开始，并一直以Master分支为基础**

```
不从任何分支开始，只从Master分支创建Feature分支，提交Merge Request将Feature合并到Master
```

9. **先修改Master分支中的错误，之后发布其他分支**

```
修改Bug应该先从Master分支创建FixBug分支修改问题，之后将其Merge到Master分支，如果这个bug影响到之前的发布版本可以 cherry-pick到其他分支（目前在开发流程上控制一个里程碑完成之前所有bug只用在master分支修复即可，里程碑版本允许存在少数bug，只需在下一个里程碑修复即可）。
```

10. **提交的信息中详细描述意图.**

```
在一次Commit和Merge时应该详细描述做了什么，甚至为什么这么做。清楚的表明此次Commit和Merge的意图
```

11. **持续集成过程中出现的问题，优先级最高.**

```
持续集成中出现的问题，优先级最高，需要立即解决（提交者或者关系人）或者回滚（开发经理），在merge代码到master进行持续集成的过程中，请等待持续集成成功再做后续事情，一旦持续集成环境出现错误，原则上不允许继续merge代码到master
```

12. **分支合并需本地先验证.**

```
feature分支和fixbug分支合并master分支时，需要在本地先merge再提交master合并
1：进入master，更新master代码 git pull；
2：切换分支 git checkout branch；
3：在分支上合并主干 git merge master --squash
4：提交合并后的代码  git commit -m ‘合并备注’
5：将代码推送到远程仓库 git push
```



### 任务管理

需求和Bug均以Issue的方式进行跟踪和管理

- 需求分析完成后，进行需求分解，理论上预估完成时间不超过3天
- 分解后的需求通过issue进行管理，赋予feature标记，issue以Feature+下划线+需求名称命名
- fixBug作为特殊任务也通过issue进行管理，bug赋予bug标记，issue以Bug+下划线+bug名称命名
- issue归属于一个里程碑
- issue完成后修改issue完成状态

### 分支管理

完整流程中包括master分支，release分支，feature分支，fixbug分支，其中master和release分支是长周期分支，feature和fixbug分支是短分支，在完成合并后删除。

- release分支保存最新可用的里程碑版本，直至最终的产品发布版本，release分支不允许直接修改
- 开发均在master分支，master分支是所有开发的起点，包括拉feature分支，fixbug分支也是源于master分支
- feature分支，fixbug分支开发完成必须在本地测试通过，以及在本地完成merge后再提交到master分支merge

### 持续集成

- 每次在有分支成功合并到master分支时自动进行持续集成，完成代码编译，代码检查，单元测试，测试报告，满足要求通过后发布到持续集成开发环境
- 每日定时从master分支进行集成，完成代码编译，代码检查，单元测试，测试报告，满足要求通过后将代码发布到每日集成开发环境

### 版本命名

软件版本号有四部分组成，第一部分为主版本号，第二部分为次版本号，第三部分为修订版

本号，第四部分为日期版本号加希腊字母版本号，希腊字母版本号共有五种，分别为base、alpha、beta 、RC 、 release



例如： release 1.10.1.20190215_release

```
Base：此版本表示该软件仅仅是一个假页面链接，通常包括所有的功能和页面布局，但是页面中的功能都没有做完整的实现，只是做为整体网站的一个基础架构。

Alpha ：软件的初级版本，表示该软件在此阶段以实现软件功能为主，通常只在软件开发者内部交流，一般而言，该版本软件的Bug较多，需要继续修改，是测试版本。测试人员提交Bug经开发人员修改确认之后，发布到测试网址让测试人员测试，此时可将软件版本标注为alpha版。

Beta ：该版本相对于Alpha 版已经有了很大的进步，消除了严重错误，但还需要经过多次测试来进一步消除，此版本主要的修改对象是软件的UI。修改的的Bug 经测试人员测试确认后可发布到外网上，此时可将软件版本标注为 beta版。

RC ：该版本已经相当成熟了，基本上不存在导致错误的Bug，与即将发行的正式版本相差无几。

Release：该版本意味“最终版本”，在前面版本的一系列测试版之后，终归会有一个正式的版本，是最终交付用户使用的一个版本。该版本有时也称标准版。
```

```
主版本号：当功能模块有较大的变动，比如增加模块或是整体架构发生变化。此版本号由项目决定是否修改。

次版本号：相对于主版本号而言，次版本号的升级对应的只是局部的变动，但该局部的变动造成程序和以前版本不能兼容，或者对该程序以前的协作关系产生      了破坏，或者 是功能上有大的改进或增强。此版本号由项目决定是否修改。

修订版本号：一般是Bug 的修复或是一些小的变动或是一些功能的扩充，要经常发布修订版，修复一个严重 Bug 即可发布一个修订版。此版本号由项目经理    决定是否修改。

日期版本号：用于记录修改项目的当前日期，每天对项目的修改都需要更改日期版本号。此版本号由开发人员决定是否修改。

希腊字母版本号：此版本号用于标注当前版本的软件处于哪个开发阶段，当软件进入到另一个阶段时需要修改此版本号。此版本号由项目决定是否修改。
```



## 参考资料

1. progit_v2.1.16.pdf
2. 持续集成与 Git 工作流  <https://xiaozhuanlan.com/topic/9423856710>
3. 推荐的源码管理策略-gitlab flow <https://blog.csdn.net/xiaosongluo/article/details/86675493>
4. Introduction to GitLab Flow  https://docs.gitlab.com/ee/workflow/gitlab_flow.html
5. The 11 Rules of GitLab Flow  https://about.gitlab.com/2016/07/27/the-11-rules-of-gitlab-flow/