Git协同工作流
中心式协同工作流
类似与svn的开发模式
开发流程:
- 从服务器上
git pull origin main
把代码拉下来. - 编写完代码以后,执行
git commit
命令提交到本地. - 执行
git push
命令,把代码推送到远程仓库中. - 其他开发人员执行
git pull
可以拉取你刚提交的代码.
这个流程是完美状态的流程,但是多人协作开发的时候,如果你本地的git不是最新版本,其他开发人员先于你提交了commit,并且推送到了远程仓库.
此时你执行第三步的时候,会发现推送不成功. 此时,你有两种办法解决这个问题,
第一种:
- 从服务器上
git pull origin main
拉取代码到本地 - 如果代码没有冲突,git会把代码自动merge,产生一条merge记录,你再执行
git push origin main
提交代码. - 如果代码有冲突,你需要解决冲突,再执行一次
git commit
, 然后提交到远程仓库.
第二种:
- 使用
git pull --rebase
命令,这种方式可以避免产生merge记录. - 这个命令的隐藏流程是git先把你的代码放一边,把服务端的代码拉下来,再把你的代码一个一个的重新commit,直到全部成功.
- 这个命令与第一个的区别就是少了merge的提交记录
如下图所示,Git 会把 Origin/Master 的远程分支下载下来,然后把本地的 Master 分支上的改动一个一个地提交上去。
如果有冲突,那么你要先解决冲突,然后做 git rebase –continue 。如下图所示,git 在做 pull –rebase 时,会一个一个地应用(apply)本地提交的代码,如果有冲突就会停下来,等你解决冲突。
优缺点:
- 优点就是简单,直观的符合大家的预期.
- 缺点就是太简单了,很难满足复杂的工作流程,并且合并冲突是一个噩梦.
功能分支协同工作流
中心式协同工作流有一个很严重的问题,就是大家都再一个主干上开发,对于小团队和小项目来说没问题,但是对于大项目,多人协作的项目就有比较严重的问题.
最大的困恼就是代码干扰太严重了.各种冲突. 没法安静的开发一个功能. 在这个基础上,我们引入了功能分支的概念.
- 使用
git checkout -b new-feature
创建new-feature
分支. - 然后共同开发这个功能的开发人员就在这个分支上工作,进行 add、commit 等操作。
- 然后通过
git push -u origin new-feature
把分支代码 push 到服务器上。 - 其他开发可以通过
git pull --rebase
来拿到最新的这个分支的代码。 - 最后通过 Pull Request 的方式做完 Code Review 后合并到 Master 分支上。
如下图,绿色的是功能分支,执行合并后的样子.
这种方式与第一种方式本质是一样的,只是多了分支的概念,也是svn中的概念,只不过是git的分支成本要远远小于svn,svn的分支合并是一种噩梦.
优缺点:
- 优点,还是简单,这种方式基本上能满足大多数小型项目的开发需求了.
- 缺点满足不了大型项目的需求.
GitFlow 协同工作流
在真是的生产环境中,前面的协同工作流还是不能满足需求,主要是因为生产环境太复杂了,在软件的开发过程中会产生各种各样的问题,还要面对不同的环境,开发环境,测试环境,预发布环境,生产环境,特性验证环境等等.
需要不断的开发新功能,也要维护线上代码,修复bug,多版本共存等等情况都是现实存在的.
- 我们希望有一个分支是绝对干净的,上面的代码都可以随时发布.上面的改动都是要马上发布到生产环境的.这个分支不能有任何中间过程的代码提交,随时都能发布生产.
- 希望当代码达到可上线状态时,也就是
alpha/beta release
时,在测试和交付的过程中,依然可以开发下一个版本的代码. - 在对已经发布到生产环境的代码,做一些Bug-fix 的改动,不会把正在开发的代码提交到生产.
- 多个版本和多个环境能够并行开发测试.
面对上面的这些要求,我们前面提的两种工作流方案都没法满足. 因为我们不仅要在整个团队中共享代码,我们还需要管理不同环境的代码互不干扰,要管理代码与环境的一致性.
为了解决这些问题, GitFlow
协同工作流就出来了。
GitFlow
协同工作流是由 Vincent Driessen 于 2010 年在 A successful Git branching model 这篇文章介绍给世人的。这个协同工作流的核心思想如下图所示。
整个代码库中一共有五种分支。
Master
分支。也就是主干分支,用作发布环境,上面的每一次提交都是可以发布的。Feature
分支。也就是功能分支,用于开发功能,其对应的是开发环境。Developer
分支。是开发分支,一旦功能开发完成,就向Developer
分支合并,合并完成后,删除功能分支。这个分支对应的是集成测试环境。Release
分支。当Developer
分支测试达到可以发布状态时,开出一个Release
分支来,然后做发布前的准备工作。这个分支对应的是预发环境。之所以需要这个Release
分支,是我们的开发可以继续向前,不会因为要发布而被block
住而不能提交。一旦Release
分支上的代码达到可以上线的状态,那么需要把Release
分支向Master
分支和Developer
分支同时合并,以保证代码的一致性。然后再把Release
分支删除掉。Hotfix
分支。是用于处理生产线上代码的Bug-fix
,每个线上代码的Bug-fix
都需要开一个Hotfix
分支,完成后,向Developer
分支和Master
分支上合并。合并完成后,删除Hotfix
分支。
这就是整个 GitFlow
协同工作流的工作过程。我们可以看到:
- 我们需要长期维护
Master
和Developer
两个分支。 - 这其中的方式还是有一定复杂度的,尤其是
Release
和Hotfix
分支需要同时向两个分支作合并。所以,如果没有一个好的工具来支撑的话,这会因为我们可能会忘了做一些操作而导致代码不一致。 - GitFlow 协同虽然工作流比较重。但是它几乎可以应对所有公司的各种开发流程,包括瀑布模型,或是快速迭代模型。
优缺点:
- 优点,基本满足的一个大的团队的开发流程.
- 缺点,分支太多,提交的git log太多,容易产生混乱,
- 需要好用的工具支持,开发工具, 自动化构建工具.
还有一个问题就是,在开发得足够快的时候,你会觉得同时维护 Master
和 Developer
两个分支是一件很无聊的事,因为这两个分支在大多数情况下都是一样的。包括 Release
分支,你会觉得创建的这些分支太无聊。
而你的整个开发过程也会因为这么复杂的管理变得非常复杂。尤其当你想回滚某些人的提交时,你就会发现这事似乎有点儿不好干了。而且在工作过程中,你会来来回回地切换工作的分支,有时候一不小心没有切换,就提交到了不正确的分支上,你还要回滚和重新提交,等等。
GitHub/GitLab协同工作流
GitHub Flow
所谓 GitHub Flow
,其实也叫 Forking flow,也就是 GitHub 上的那个开发方式。
- 每个开发人员都把“官方库”的代码 fork 到自己的代码仓库中。
- 然后,开发人员在自己的代码仓库中做开发,想干啥干啥。
- 因此,开发人员的代码库中,需要配两个远程仓库,一个是自己的库,一个是官方库(用户的库用于提交代码改动,官方库用于同步代码)。
- 然后在本地建“功能分支”,在这个分支上做代码开发。
- 这个功能分支被 push 到开发人员自己的代码仓库中。
- 然后,向“官方库”发起 pull request,并做 Code Review。
- 一旦通过,就向官方库进行合并。
这就是 GitHub
的工作流程。如果你有“官方库”的权限,那么就可以直接在“官方库”中建功能分支开发,然后提交 pull request。通过 Code Review 后,合并进 Master 分支,而 Master 一旦有代码被合并就可以马上 release。这是一种非常 Geek 的玩法。这需要一个自动化的 CI/CD 工具做辅助。是的,CI/CD 应该是开发中的标配了。
GitLab Flow
然而,GitHub Flow 这种玩法依然会有好多问题,因为其虽然变得很简单,但是没有把我们的代码和我们的运行环境给联系在一起。所以,GitLab 提出了几个优化点。
其中一个是引入环境分支,如下图所示,其包含了预发布(Pre-Production)和生产(Production)分支。
而有些时候,我们还会有不同版本的发布,所以,还需要有各种 release 的分支。如下图所示。Master 分支是一个 roadmap 分支,然后,一旦稳定了就建稳定版的分支,如 2.3.stable 分支和 2.4.stable 分支,其中可以 cherry-pick master 分支上的一些改动过去。
这样也就解决了两个问题:环境和代码分支对应的问题;版本和代码分支对应的问题。
Ours后端协同工作流
以上的几个git工作流,都是业界主流的方案,没有那个绝对好,绝对坏,需要根据团队的情况选择.
我们后端团队根据实际情况, 设计了一套工作流方案,目前应用下来还比较丝滑,能够满足现阶段的开发需求.
我们的项目分为两类:
- 所有人共同开发的项目/多人共同开发的项目,如bff网关,后台网关等.
- 单人开发或2人开发的项目,如基础组件/单个rpc项目.
根据这两类项目,我们分为不同的开发发布流程.
- 所有项目都有4个固定的环境分支,生产环境,预发布环境,测试环境,开发环境.
- 每个环境都有自动化构建脚本,其中开发,测试通过commit触发(每次提交都执行一次构建),预发布和线上通过tag触发(打固定格式的tag会触发构建),构建后的产物上传到产物仓库.
- 开发和测试普通开发人员可以直接提交,预发布和生产必须通过提PR的形式,由审核人员审核代码才能合并.
- 多人项目执行
GitFlow 协同工作流
工作流, 每个人有自己的个人分支和共同的版本分支,大版本的时候所有版本代码都合并到版本分支上,再从版本分支合并到开发环境,测试环境,预发布环境,线上环境. - 单人小项目,执行基本
功能分支协同工作流
,再开发分支上开发,依次合并到测试分支,预发布,线上.
以下是多人协作分支架构图:
以下是开发流程图:
协同工作流的启示
通过以上的git工作流的比较和思考,会发现,没有绝对好的方案,只有适合的方案,每个团队有不同的开发习惯和版本发布周期, 所以选择工作流需要找到最适合团队情况的,并且要能满足需求的方案.
- 协同工作流不是玩好代码仓库的分支策略,而是基于分支策略保证我们软件的开发流程是高效且稳定的.
- 要相信流程,而不是相信人,代码的合并和编译构建,一定要让脚本去完成,而不是开发人员本地去构建.
- 工具很重要,磨刀不误砍柴工,拥抱工具,减少无意义的重复劳动.