从亲身经历谈谈如何用Git分支解决项目生产实践中的痛点

2020-09-16 16:28:03 浏览数 (1)

最近笔者所在公司发生了一起小风波,事情大概是这样的:市场部老大在给客户现场演示系统时,正讨论着一个主题,恰巧系统在切换到相关功能时出现了异常,导致功能不可用,现场有点尴尬。

显然,问题归咎于研发部。严肃的气氛下,我下意识在想自己是不是凉了,于是我迅速定位原因,发现是后端接口发生变更而未通知前端,责任人正好是刚来没多久的后端新人。虽然这次事故不是前端的责任,但让我发现了后端Team存在的问题,在版本控制上有较大的隐患,代码未经Review就入库发版了,这本质上是分支管理不合理导致的。

研发部门是一个整体,当着客户的面出了生产事故,这让大家面子上都不好看,所以我自告奋勇提出在研发部内部做一次Git分支管理的分享,看看能不能帮大家解决这个问题。我入职以来一直比较注意版本控制这块,但也是今年才比较系统地梳理研发流程版本控制(去年是快速出产品的一年,管理上稍微糙一点),几个月前还特意总结了一篇《前端小微团队的Gitlab实践》,经过数月的不断实践和改进,我感觉这套Git体系基本覆盖了我司的研发流程,至今没出过事故,发版节奏一直良好。

其实几个月前我就想在部门内分享下我这套版本控制流程,但是一方面是考虑到自己刚摸索出来,不太熟练,另一方面是自己资历尚浅,如果跨Team直接给后端老哥们“上课”也不太好吧(其实这个顾虑是多余的~_~)。

嗯,大概是这么一个心路历程,而现在正是必须站出来的时候,我希望这次我的分享能为团队尽绵薄之力!具体分享的内容是这样的,且听我慢慢道来!

个人感受

Git对我们来说既熟悉又陌生。感觉熟悉是因为我们似乎已经掌握了大量常用的Git命令,感到陌生是因为我们在实际项目中总是用不好它。是的,我也有过这样的感受,直到现在,我觉得Git仍有很多待探索的空间,比如难以理解的git rebase,又或者是Git提供的Hooks,让自动化部署有了更多可能。甚至一些平台将代码托管敏捷开发CI/CDDevOps融合到了一起,提供了一站式解决方案。

始于Git,却不止于Git,Git还有太多值得我们折腾的小惊喜。那么,今天我以如何在实际项目中运用Git分支管理这个主题作为切入点做一次内部分享。

分布式版本控制

我们知道,Git是一个开源的分布式版本控制系统,这让团队协作成为了可能。我们可以通过fetch/pull将远程仓库的代码拉取到本地,也可以将本地代码push到远程仓库。

而我们向版本库提交代码的一个基本方向是:

工作区 --> 暂存区 --> 版本库

  • 当对工作区修改(或新增)的文件执行git add命令时,暂存区的目录树被更新。
  • 当执行git commit命令进行提交操作时,暂存区的目录树写到版本库中。

分支管理

Git最核心的内容当然是分支管理,设置合理的分支可以让研发流程有条不紊。使用分支意味着你可以从开发主线上抽离出来,不影响主线的前提下进行工作,最后完成工作再通过git merge将代码合入到主干分支上。

简单的分支管理

在生产实践中,一般来说,我们会保持至少三个分支,分别是开发分支develop测试分支release生产主干分支master。不同的团队或个人在分支命名上可能会有所差异,但是基本逻辑都是大体一致的。

  • 开发分支develop最不稳定的分支,所有和特性,缺陷相关的代码都会陆续地被提交到这个分支。
  • 测试分支release:一个敏捷迭代结束时,正常情况下,所有develop分支的代码都会被mergerelease分支,准备发测试版本。
  • 生产分支master最稳定的分支,待交付的版本上线前,测试通过的release分支会被mergemaster分支。

然而很多团队在管理develop分支时存在一个很大的问题:所有开发者都直接向develop分支push代码

这样会造成很多隐患,包括但不限于:

  • 团队成员间代码冲突。当然,直接向develop分支push代码也不是造成冲突的根本原因。但是,这会让冲突更容易发生!
  • 代码质量不可控。这个问题大家都比较清楚了,这是因为所有代码都没有经过Review就入库了!
  • 版本不可控。相信大家都遇到过,临到上线时间点,突然发现某某开发者的转测功能存在重大缺陷,不能上线。这个时候,选出能上线的代码让人头疼!根本原因是开发者的代码都直接进了develop分支,这让挑选代码变成了一件非常复杂的事情!

可控的分支管理

那么如何才能解决上述痛点呢?我们可以从分支的设计上入手。

  • 保护分支(Protected Branchs)。禁止开发者直接向保护分支提交代码,developreleasemaster都应该被设置为保护分支!
  • 增加特性/缺陷分支,避免直接向develop分支push代码。
  • 增加代码Review环节,基本上所有代码托管平台都支持这个环节!

具体操作流程是这样的:

  1. 如上图所示,我们约定一个特性或一个缺陷就是一个开发任务,所有的开发任务都应该在本地建立独立的分支
  2. 开发者在特性/缺陷分支上进行开发。由于我们禁止了向保护分支直接push代码,所以开发者完成代码编写后,需要将本地分支同步到远程同名分支
  3. 在代码托管平台如Gitlab上发起Merge Request,请求将特性/缺陷分支合入到develop分支。
  4. Maintainer(一般是团队资深成员,拥有同意MR的权限)负责Code Review,确认基本无误后同意MR,代码就顺利进入develop分支了。
  5. 后面全量发版本的流程就简单了,无脑merge即可!
  6. 如果不能全量发版,必须进行代码挑选,此时就需要cherry-pick出场了!

特别注意,一定要保证分支的原子性,一个分支只干一件事。千万不要写着写着代码,突然萌生了在当前分支顺手改另一个问题的想法,这可能会让你陷入更大的麻烦!

分支命名

取名字永远是个难题,组件如何命名,方法如何命名,这些问题在平时开发过程中总是让人抓耳挠腮。当然,Git分支命名也不例外。

我之前也试过分支语义化命名,但是也发现了要用有限的单词描绘出复杂的含义永远是个伪命题。如上图所示,我们可能会在做一个新功能时,把相关分支命名为feature/xxx,而后面有优化类需求时,又会新建一个feature/xxx-optimization之类的分支。然而,往往一个功能会有一次又一次的优化、变更或bug,采取这样的命名策略永远会让自己直面灵魂拷问!

并且在追溯问题时,这种分支命名方式往往让人心力交瘁!

那么如何命名能解决这样的问题呢?我采用了下面这种策略!

我在观察很多开源软件时发现,他们的维护者都会用issue来记录各种开发相关的活动。比如需求,缺陷都会被记录在issue中,这让我觉得用issue来管理分支也是一个非常棒的idea!

我们可以在创建issue时填写标题和描述,并且可以通过链接等形式与敏捷管理平台的需求和缺陷关联上,还可以给issue打上不同的标签,看起来会非常直观。

issue还可以与milestone(里程碑)关联,用于检验和衡量阶段性的成果!想要知道更多细节,不妨打开《前端小微团队的Gitlab实践》细致阅读!

而issue本身有一个编号,或者叫ID,这种唯一标识让我们命名分支变得简单。假定一个issue的编号是1,那么我们在本地创建分支时,只需要将分支命名为issue/1即可,根据这个编号,我就能查到这个分支处理的是哪个issue,而打开Gitlab的issue,我就能知道这个issue与什么需求或缺陷有关。这不仅给开发者带来了方便,也让管理者变得更轻松!

实际项目中如何操作?

对上文中的知识有了一定了解后,接下来就是看看如何在项目中把这些知识运用起来,形成一个合理,高效的流程!我以新需求为例,简单画了一下流程,请看下图:

打通了这么一个主流程后,相信无论是修复bug,还是其他的场景,你都能举一反三

分支节点可拓展

实际上,不同公司在分支节点上的数量是不一样的。有的公司可能从开发到上线,会涉及多套环境验证,这样下来,就可能对应多个Git分支节点。加节点也不用怕,结合git mergegit cherry-pick,理论上再多节点也能应付得过来!

所以,我也在内部分享结尾时,提出了增加预发布环境的建议。测试环境尽可能发挥想象,可以测试各种极端情况。而预发布环境尽量模拟生产环境,保证数据和流程的合理性。这样一来,结合测试环境和预发布环境,我们能覆盖更多的测试用例,上线故障率会更低!

VSCODE必备扩展:GitLens

最后推荐大家安装一个非常好用的VSCODE扩展:GitLens

有了它,我们就可以随时看到每一行代码最近一次的改动都是谁提交的。

这也避免了大家查问题时,突然翻到一行可疑代码,然后感叹:这是哪个傻X写的!

最后一查记录发现是自己写的......

科科,GitLens它不香吗?

0 人点赞