多人多团队协作开发的大项目如何进行Git管理

6,454 阅读9分钟

前言

Git是目前市场上最流行的代码版本管理工具,它的重要性无须我再强调,掌握Git使用已经是程序员一种入门必备的技能。这里肯定有同学说:Git使用不就那几个命令行一把梭吗?不然就用sourseTree轻松点一点!说这些话的同学多半是没有经历过:一夜之间代码回到解放前,导致十几个开发同学连续一个星期加班加点恢复代码!然后被劝退回家的惨痛经历!当然笔者也没有,只是笔者是那十几个中的一猿。

Git的规范使用可能对于1到2个人单线程协作方式的小团队无感,但是对于多人协作的中大型项目就显得特别的重要!一个好的Git管理规范也是需要时间去打磨和验证的。

去年笔者参与了一个特别大型的toB项目,量级是上百个模块,是多人多团队协作的开发形式。当时团队面临着一个非常大的挑战就是如何进行代码版本管理,过程中开过无数次会议进行研讨,尝试了很多的方案,把该踩的雷给踩了,不该踩的也踩了(捂脸)。 例如代码覆盖啊,环境污染,迭代版本被阻塞等等。经过一年的不断的修正实践最终总结了一套比较通用的Git管理规范。那么到底该如何进行Git对大项目管理呢?答案是先定制一套合适的工作流!

常见Git工作流

集中式工作流

流程说明

全流程只有一个master分支,类似svn的工作流模式,开发整个过程在本地进行,开发结束直接在本地提交测试,测试通过再push到master。

特点:全程只需维护一个master,没有额外的分支管理开销。

缺点:单线程工作流,无法同时进行多个任务开发,而且一个任务只能一个人负责。

适用对象:不需要协作和合流的小项目,例如一些官网,活动等项目

功能分支工作流(Github flow)

流程说明

新功能在master创建功能分支feature,开发结束通过在客户端UI发起 pull requests请求指定review 人 admin,由admin review通过后合到master。

特点:流程简单,实现功能代码相互隔离,提交的代码通过pull requests可以让团队成员之间互相评论。

缺点:线上版本和master不同步时需要另外新建一个product分支跟踪线上版本(苹果商店的APP提交审核以后,等一段时间才能上架)。

适用对象:持续发布的项目,例如一些开源项目

Gitflow工作流

gitflow是比较常用的工作流,可能细节每个团队规范不一样,但是主体结构和思想是一致的,都是由:feature、develop、release、master、hotfix分支组成。我们曾以gitflow工作流作为我们的 工作流,在过程中发现分支流程过程中过于复杂,对新手不友好,而且每个功能开发feature分支都在develop分支汇合,会导致同段时间进行开发的功能,必须同时上线

比如同时提测的两个功能需求,其中一个已经测试完毕的A功能,另一个没有测试通过被打回的B功能,这时是无法撤回develop上的B,导致A一直等待B。

流程说明

流程从develop建立功能分支feature,完成开发后push回develop进行测试,在develop建立测试服缺陷修复分支fixbug,完成测试环境验收后,在develop新建release分支作为验收环境的分支,验收完成并封版后合并到master和develop。

特点:清晰可控,多线程工作流,可以多人协作完成一个大任务,并且可以并行多个功能任务,任务可以从本地环境到正式环境一层一层向上推动,各个环境相互不影响。

缺点:相对复杂(经常需要切换分支),若有多个任务同时进行的,必须同一个版本迭代,存在版本污染风险。

适用对象:版本迭代不太频繁、多人协作开发的中小项目

定制Git工作流

Gitflow加强版工作流

‘心形’工作流是我们团队目前稳定使用的工作流,它新分支建立必须基于‘干净的分支’master,它跟gitflow不一样的是,feature推动整个研发周期进行,develop分支只作为测试环境的测试分支。

流程说明

功能开发完成后feature合并到develop,测试通过后基于 master创建发布分支release,release合并开发feature分支后,部署上线, 验收通过并封版后合到master,看需要来打tag。(这里没有画缺陷修复流程,是因为其流程跟功能开发几乎一样,区别是:hotfix最终是合回上一个迭代版本的release分支,而新功能feature是新建一个release分支)

特点:兼备了Gitflow所有优点同时也弥补了缺点

缺点:合并动作会重复,冲突需要解决2次(因为功能代码不是从develop推上master,如果在合develop存在的冲突,到了合master也会存在冲突)。

适用对象:版本迭代频繁、多人协作开发的中大型项目

注意: 开发/缺陷分支只能合并稳定分支例如可以合并master分支,不可merge develop分支,作用是防止环境污染develop分支只能用于测试环境发布,不可直接合并到release分支,正确流程是在release分支合并开发/缺陷分支,具体看下面的表格。

分支管理规范

分支类型

分支说明

开发分支: feat/xxx(功能)_20200804(创建日期)

开发分支基于master创建,开发完成合并到测试develop分支

测试分支:develop

develop分支只用来发布测试环境

发布分支:release/vx.x.x(版本号)_20200804(创建日期)

基于master创建,验收完成,进行封版后合并回master

缺陷分支:hotfix/xxx(功能)_20200804(创建日期)

合并流程和开发分支一致,区别在于,hotfix 在测试环境测试通过后直接合到最新的 release 分支验收

其他

个人认为上线之后的缺陷才算 bug ,未上线的缺陷是功能不完善,对于未上线的缺陷直接在 feature 分支修复即可, 当任务/功能上线之后出现的缺陷才需要建立 hotfix 分支作为修复 bug ,另外建议保留最新的 release 分支。原因是 该版本的线上 bug 修复后在测试环境验收通过后需要合并到该版本的 release 分支进行发布预发布环境。 当然也可以合到下一个版本的 release 分支。看项目迭代周期,如果迭代周期长,又有一些紧急的 bug 的话合到下一个 版本的 release 就不合适,另外当任务上线后验收成功后在 master 打 tag 记录当前的版本。

Git操作规范

Git使用规范

commit 规范

feat: ⼀个新特性

fix: 修了⼀个 Bug

docs: 更新了⽂档(⽐如改了 Readme)

style: 代码的样式美化,不涉及到功能修改(⽐如改了缩进,css修改不算)

refactor: ⼀些代码结构上优化,既不是新特性也不是修 Bug(⽐如函数改个名字)

perf: 优化了性能的代码改动

test: 新增或者修改已有的测试代码

chore: 跟仓库主要业务⽆关的构建/⼯程依赖/⼯具等功能改动(⽐如新增⼀个⽂档⽣成⼯具)

操作规范(技巧)

在代码push 前先 pull

遇到代码冲突时,最先考虑取最近commit的版本,若想撤销本次拉取 执行git revert --abort

正在开发发现分支错了,执行 git stash,切换分支后,执行git stash pop

只想合并其他分支的某条commit 记录 执行 git cherry-pick commitId

开发分支新建必须基于干净版本,合并到稳定版本前必须是验收通过的版本

开发分支不能合并其他正在开发或者非干净分支

常用Git命令

git remote prune origin      删除本地有但在远程库已经不存在的分支 <br>
git clone -b   分支名 地址 <br>
git remote add origin git@github.com:XXXXX/demo.git   新增远程仓库<br>
git remote set-url origin git@github.com:XXXXX/demo.git  修改远程仓库<br>
git remote set-url --add origin git@github.com:XXXXX/demo.git  添加多个远程仓库<br>
git stash    不提交工作区内容 <br>
git stash pop 恢复工作区<br>
git fetch   拉取远程分支<br>
git reset --hard <commit ID号> 回滚<br>

git push -f origin master 推送到远程分支 <br>
git diff    查看工作区和暂存区的区别 <br>
git diff –cached    查看暂存区和版本库之间的区别 <br>
git diff HEAD   查看工作区和版本库之间的区别 <br>
git status   查看当前的工作状态<br>

git push --set-upstream origin online_help_20191024   推远程分支<br>
git push origin --delete dev20181018    删除远程分支<br>
git branch -d dev20181018   删除本地分支<br>
git cherry-pick 285c9477a759abdee94099e25e75e39e8c77d46b 合并指定版本

命令流程图

整个流程共4个存储区,我们在gitLab/gitHub新建仓库【远程仓库】,通过clone到本地,然后我们进行本地编程,此时我们本地就是我们的【工作区】,当我们执行add后我们的代码就存到【暂存区】,当执行commit之后我们的代码就存到的【本地仓库】,这里【工作区】【暂存区】【本地仓库】代码都是存储在我们的本地,其他人是无法进行共享的。

写在最后

曾经有同学让我给推荐Git图形工具,而我回复的是:不要用图形工具。太依赖工具不是件好事,它仅仅只会让你越来越依赖工具,却没有太多的效率提升。

最后欢迎大家留言交流。