一、简介
????????Git是分布式版本控制系统,与之对应另一种常用的SVN是集中式版本控制系统。它们的差异很大,主要是源于它们的设计思想,这里就不展开细说,大家可以自行查找资料。总体来说,Git更灵活、对工作环境依赖更小、更适合多人团队的协同工作,但是学习成本更高,如果仅仅是用Svn的方式去使用它,那就几乎和Svn一样没有什么学习成本,但是之所以选择了Git,就是要充分利用它的优点,从而使我们的项目代码管理更加有效、合理,提高协同工作效率。互联网上Git托管平台有:GitHub,国内的有Gitee。
二、分支
1、概念
????????在Git使用过程中,我们从始至终都在和分支打交道,分支可以说是最重要的,也是使用Git所必须要掌握的一个点。 ????????分支的概念很好理解,顾名思义,就像一颗树,从主干出来可以衍生无数个树枝,但是在Git中没有实际上的主干,每个分支都是可以作为主干,因为每个分支就是一个副本,每个分支都可以不依赖于其他分支。通常在项目建立后,我们会人为的确认一条分支作为主干,这条主干将放在我们的中央存储仓库中,提供给各开发人员作为基线。 ????????在Git中,当新创建了仓库后,就会默认创建一个分支,名称为master,我们可以在该分支上创建多次提交,并以任意提交为基础,新创建任意个分支。(注意:如果master还未创建提交,此时新创建了分支,那么此操作相当于对master分支进行重命名)。 ????????如上图,共存在5个分支,不同的开发人员可以并行的在不同分支上进行编码工作并提交,它们之间互不影响。
????????一个项目在持续开发和迭代中主要有几个阶段:功能开发、问题修复、版本发布、紧急问题修复、版本迭代。这个过程中,每个阶段并不是完全是时间顺序的,可能是并行的,也可能涉及到多人的协同工作。但最终目的是输出稳定的发布版本,Git分支对这个过程的工作提供了强大而灵活的支持。
2、原则
????????虽然可以在任意分支上创建任意个子分支,但是在实际项目开发过程中,团队内部需要制定一个规则用于指导分支的创建,比如:
- 创建时机
通常是在开发人员接收到新功能需求或者被指派了问题修复任务时,需要以主分支或者开发主分支为基础新创建出子分支。 - 用途
需要明确分支的用途,即它是用于开发新功能,还是用于修复问题,必须确保它的用途单一,不能混合在一起。比如不允许一个分支即用于新功能开发,同时用于问题修复(同个功能需求内的除外),这样不利于问题的追溯。 - 命名规范
分支的命名相对比较自由,但有比要定义一下团队内部的规范,通常是根据用途进行命名,比如新功能分支以feature/ 为前缀,加上功能名,如:feature/sms_login ,问题修复分支以fix/ 为前缀,加上问题描述,如:fix/user_table_query_fail 。
3、协同
????????方才所说,分支本质上是独立互不依赖的,这为团队协同工作提供了极大便利性,但是一个版本或者大功能的完整性则需要集合各分支上的代码,因此需要指定一个分支作为主分支,当其他分支上的代码已编码结束并完成测试时,需要把该分支的提交整合到主分支,这个操作叫做合并,协同工作因此变为可能。
三、合并
????????对Git分支进行合并操作有两种方式,merge 和rebase ,它们的设计思想有较大不同,在实际的项目开发中,应用的场景也有所不同。
1、merge
????????合并,把指定分支(假设为分支B)的代码修改合入到当前分支(假设为master),它提供了两种模式:
- Fast Forward
快进模式,合并后会直接将当前分支master的HEAD指向指定分支B的HEAD。 - No Fast Forward
在合并时会生成一个新的提交到当前分支master,该提交包含了指定分支B的所有私有提交。
两种模式的模型图: ????????如果当前分支master和要合并的分支B都有自己独有的提交时(即合并的分支B与当前分支master的最近公共提交不是当前分支master的最新提交),则无法使用Fast Forward进行合并。 两种模式比较:
- Fast Forward
优点: (1)当有大量分支,且进行大量合并时,该模式不会产生大量的分支合并记录,使提交记录图谱看起来更简洁清晰。 (2)避免在当前分支产生冲突,规定了指定的分支必须是基于当前分支的最新提交,可以从机制上降低当前分支风险。 缺点: (1)由于丢失了分支合并信息,无法追溯分支合并历程。 - No Fast Forward
优点: (1)保留每次的分支合并信息,方便追溯分支历程。 缺点: (1)当分支合并次数太多时,提交记录的图谱不够简洁,不便利阅读和分析。 (2)容易在当前分支产生冲突,需要手动去解决冲突,从机制上增加了当前分支代码稳定性的风险。
????????Git进行merge时默认使用Fast Forward,不成功时则自动切换为No Fast Forward,可以在merge时手动指定使用哪种模式。
2、rebase
????????变基,本质是丢弃当前分支现有的提交,然后把HEAD移动到另一个分支的HEAD,最后把当前分支已丢弃提交的内容重复提交一遍,这样就实现了把指定分支的提交同步到当前分支的效果。注意: 被丢弃的提交并不会被删除,实际上还会占用磁盘空间。 ????????由上面的模型可以看到,变基后的分支B,master分支可以使用Fast Forward对它进行合并。注意: 使用rebase,提交记录的时间并不一定是按照顺序的。
3、原则
????????合并提供了多种方式,它们各有优缺点,采用哪种方式主要是看项目团队自己的喜好和风格。基于经验之谈,很多公司都是采用这样的原则:
- 公共分支
一般规定要使用merge操作的Fast Forward模式进行合并,这是为了保证提交记录的线性显示,同时降低了代码冲突风险。说明: 保留分支合并信息实际上对大多数项目来说并无多大意义且增加了风险控制成本。 - 私有分支
私有分支一般只由一个开发人员维护,通常都是子分支,因此它的基点可能会落后与主分支,此时规定使用rebase操作,把私有分支变基到主分支的最新提交。这样的好处是,方便当前分支的回退到某次提交,而且当主分支需要合并私有分支时可以使用Fast Forward。说明: 私有分支在被合入主分支后,一般需要把它删除。
四、代码管理规范
1、目的
- 规定了公司软件代码管理规范。
- 提高协同开发效率。
- 提高代码稳定性和可追溯性。
2、适用对象
3、原则
角色 | 职责 | 权限 |
---|
Git管理员 | 1、创建仓库 2、检查分支规范 3、维护后台系统 | 创建、修改 | 开发主管 | 1、管理项目公共分支(master、develop) 2、成员管理 3、标签(tag)管理 4、代码审核 | 创建、修改 | 开发人员 | 1、创建私有分支(功能分支、Bug修复分支) 2、代码开发和提交 3、提交MR(合并请求) | 修改 | 测试人员 | 对master和develop版本进行测试 | 查看 |
4、分支管理
-
主分支(master) ????????提供了最稳定的版本,只合并develop和hotfix,合并后需要打tag(用于标识版本),可支持随时从指定的tag处发布版本到线上。必须有以下特性:
- 不允许直接commit和push,只能通过MR合并。
- 限制merge权限,只允许指定人员(通常是开发主管)执行。
- 只允许满足Fast Forward条件的合并。
-
开发分支(develop) ????????始终保持最新的代码和bug的修复,进入新版本迭代时,必须新创建一个开发分支,命名规范:develop/版本号 ,示例:develop/3.0.1 。必须有以下特性:
- 不允许直接commit和push,只能通过MR合并。
- 限制merge权限,只允许指定人员(通常是开发主管)执行。
- 只允许满足Fast Forward条件的合并。
- 每次合并前都需要进行CR。
- 只有功能完整并测试稳定后,才允许向master提交MR。
-
功能分支(feature) ????????开发新功能时,必须以develop为基础新创建一个功能分支,命名规范:feature/功能名 ,示例:feature/finger_login 。 ????????该分支为开发人员的私有分支,通常只有一个开发人员在此分支进行代码修改和提交,当自测没问题时,才可以提交MR到develop,并告知develop的负责人(通常是开发主管)进行合并,合并后本分支需要删除。**注意:**在功能开发过程中,develop分支可能有了新的提交,那么develop的合并将会失败,必须先在本分支rebase到develop后再提交MR,不能使用merge操作,根据经验,开发过程中最好经常pull下远端的develop,然后对本分支进行rebase下。 -
修复分支(fix) ????????版本开发期间,若有发现bug,必须以develop为基础新创建一个修复分支,命名规范:fix/问题简述 ,示例:fix/com_data_loss 。 ????????该分支为开发人员的私有分支,其开发和合并过程同功能分支。 -
紧急修复分支(hotfix) ????????在某个版本上线后,若发现了需要紧急修复的bug,则必须从master的最新提交新创建一个紧急修复分支,命名规范:hotfix/版本号_问题简述 ,示例:hotfix/3.0.0_login_crash 。 ???????? 该分支为开发人员的私有分支,需要测试验证没问题后,才可以提交MR到master,注意: 若master已经有新的提交,需要先rebase。 ????????通常合入到master后,develop也要跟着合入此修复,develop合入过程:
- 需要先以develop为基础新创建一个合入分支,分支命名不限(因为只是临时的),比如:
merge/3.0.0_login_crash 。 - 如果此hotfix分支产生了几十上百个大量的提交,则:使用merge方式把
hotfix/3.0.0_login_crash 合入到merge/3.0.0_login_crash ,然后提交MR到develop。此时会产生分支合并信息。 - 如果此hotfix分支只产生少量几个提交,则:使用rebase方式把
merge/3.0.0_login_crash 变基到master(注意: 这是个例外,功能分支和修复分支正常是限制直接从master拉取数据),然后提交MR到develop。 - 尽量使用rebase方式。
5、工作流
6、日志规范
????????每次在分支上进行提交时,都需要添加提交日志,且遵循一定的日志说明规范,这样有利于问题追溯,同时可以利用工具根据每个提交自动生成CHANGELOG。日志提交格式
|