Git协同工作流

中心式协同工作流

类似与svn的开发模式

开发流程:

  1. 从服务器上 git pull origin main 把代码拉下来.
  2. 编写完代码以后,执行git commit 命令提交到本地.
  3. 执行 git push命令,把代码推送到远程仓库中.
  4. 其他开发人员执行git pull 可以拉取你刚提交的代码.

这个流程是完美状态的流程,但是多人协作开发的时候,如果你本地的git不是最新版本,其他开发人员先于你提交了commit,并且推送到了远程仓库.

此时你执行第三步的时候,会发现推送不成功. 此时,你有两种办法解决这个问题,

第一种:

  1. 从服务器上 git pull origin main拉取代码到本地
  2. 如果代码没有冲突,git会把代码自动merge,产生一条merge记录,你再执行git push origin main提交代码.
  3. 如果代码有冲突,你需要解决冲突,再执行一次git commit, 然后提交到远程仓库.

第二种:

  1. 使用 git pull --rebase命令,这种方式可以避免产生merge记录.
  2. 这个命令的隐藏流程是git先把你的代码放一边,把服务端的代码拉下来,再把你的代码一个一个的重新commit,直到全部成功.
  3. 这个命令与第一个的区别就是少了merge的提交记录

如下图所示,Git 会把 Origin/Master 的远程分支下载下来,然后把本地的 Master 分支上的改动一个一个地提交上去。 /images/2023-05/8773994f45327b848fb6a15400250621.webp

如果有冲突,那么你要先解决冲突,然后做 git rebase –continue 。如下图所示,git 在做 pull –rebase 时,会一个一个地应用(apply)本地提交的代码,如果有冲突就会停下来,等你解决冲突。 /images/2023-05/44c7d4d0dcbc008a509f22b6873dc414.webp

优缺点:

  1. 优点就是简单,直观的符合大家的预期.
  2. 缺点就是太简单了,很难满足复杂的工作流程,并且合并冲突是一个噩梦.

功能分支协同工作流

中心式协同工作流有一个很严重的问题,就是大家都再一个主干上开发,对于小团队和小项目来说没问题,但是对于大项目,多人协作的项目就有比较严重的问题.

最大的困恼就是代码干扰太严重了.各种冲突. 没法安静的开发一个功能. 在这个基础上,我们引入了功能分支的概念.

  1. 使用 git checkout -b new-feature 创建 new-feature分支.
  2. 然后共同开发这个功能的开发人员就在这个分支上工作,进行 add、commit 等操作。
  3. 然后通过 git push -u origin new-feature 把分支代码 push 到服务器上。
  4. 其他开发可以通过git pull --rebase来拿到最新的这个分支的代码。
  5. 最后通过 Pull Request 的方式做完 Code Review 后合并到 Master 分支上。

如下图,绿色的是功能分支,执行合并后的样子.

/images/2023-05/55fb5a12b11fb1f2e7526a99b3151a6b.webp

这种方式与第一种方式本质是一样的,只是多了分支的概念,也是svn中的概念,只不过是git的分支成本要远远小于svn,svn的分支合并是一种噩梦.

优缺点:

  1. 优点,还是简单,这种方式基本上能满足大多数小型项目的开发需求了.
  2. 缺点满足不了大型项目的需求.

GitFlow 协同工作流

在真是的生产环境中,前面的协同工作流还是不能满足需求,主要是因为生产环境太复杂了,在软件的开发过程中会产生各种各样的问题,还要面对不同的环境,开发环境,测试环境,预发布环境,生产环境,特性验证环境等等.

需要不断的开发新功能,也要维护线上代码,修复bug,多版本共存等等情况都是现实存在的.

  1. 我们希望有一个分支是绝对干净的,上面的代码都可以随时发布.上面的改动都是要马上发布到生产环境的.这个分支不能有任何中间过程的代码提交,随时都能发布生产.
  2. 希望当代码达到可上线状态时,也就是alpha/beta release 时,在测试和交付的过程中,依然可以开发下一个版本的代码.
  3. 在对已经发布到生产环境的代码,做一些Bug-fix 的改动,不会把正在开发的代码提交到生产.
  4. 多个版本和多个环境能够并行开发测试.

面对上面的这些要求,我们前面提的两种工作流方案都没法满足. 因为我们不仅要在整个团队中共享代码,我们还需要管理不同环境的代码互不干扰,要管理代码与环境的一致性.

为了解决这些问题, GitFlow 协同工作流就出来了。

GitFlow 协同工作流是由 Vincent Driessen 于 2010 年在 A successful Git branching model 这篇文章介绍给世人的。这个协同工作流的核心思想如下图所示。

/images/2023-05/9cf0d9de4151269d4dd59f7519d51452.webp

整个代码库中一共有五种分支。

  • Master 分支。也就是主干分支,用作发布环境,上面的每一次提交都是可以发布的。
  • Feature 分支。也就是功能分支,用于开发功能,其对应的是开发环境。
  • Developer 分支。是开发分支,一旦功能开发完成,就向 Developer 分支合并,合并完成后,删除功能分支。这个分支对应的是集成测试环境。
  • Release 分支。当 Developer 分支测试达到可以发布状态时,开出一个 Release 分支来,然后做发布前的准备工作。这个分支对应的是预发环境。之所以需要这个 Release 分支,是我们的开发可以继续向前,不会因为要发布而被 block 住而不能提交。一旦 Release 分支上的代码达到可以上线的状态,那么需要把 Release 分支向 Master 分支和 Developer 分支同时合并,以保证代码的一致性。然后再把 Release 分支删除掉。
  • Hotfix 分支。是用于处理生产线上代码的 Bug-fix,每个线上代码的 Bug-fix 都需要开一个 Hotfix 分支,完成后,向 Developer 分支和 Master 分支上合并。合并完成后,删除 Hotfix 分支。

这就是整个 GitFlow 协同工作流的工作过程。我们可以看到:

  • 我们需要长期维护 MasterDeveloper 两个分支。
  • 这其中的方式还是有一定复杂度的,尤其是 ReleaseHotfix 分支需要同时向两个分支作合并。所以,如果没有一个好的工具来支撑的话,这会因为我们可能会忘了做一些操作而导致代码不一致。
  • GitFlow 协同虽然工作流比较重。但是它几乎可以应对所有公司的各种开发流程,包括瀑布模型,或是快速迭代模型。

优缺点:

  1. 优点,基本满足的一个大的团队的开发流程.
  2. 缺点,分支太多,提交的git log太多,容易产生混乱,
  3. 需要好用的工具支持,开发工具, 自动化构建工具.

还有一个问题就是,在开发得足够快的时候,你会觉得同时维护 MasterDeveloper 两个分支是一件很无聊的事,因为这两个分支在大多数情况下都是一样的。包括 Release 分支,你会觉得创建的这些分支太无聊。

而你的整个开发过程也会因为这么复杂的管理变得非常复杂。尤其当你想回滚某些人的提交时,你就会发现这事似乎有点儿不好干了。而且在工作过程中,你会来来回回地切换工作的分支,有时候一不小心没有切换,就提交到了不正确的分支上,你还要回滚和重新提交,等等。

GitHub/GitLab协同工作流

GitHub Flow

所谓 GitHub Flow,其实也叫 Forking flow,也就是 GitHub 上的那个开发方式。

  1. 每个开发人员都把“官方库”的代码 fork 到自己的代码仓库中。
  2. 然后,开发人员在自己的代码仓库中做开发,想干啥干啥。
  3. 因此,开发人员的代码库中,需要配两个远程仓库,一个是自己的库,一个是官方库(用户的库用于提交代码改动,官方库用于同步代码)。
  4. 然后在本地建“功能分支”,在这个分支上做代码开发。
  5. 这个功能分支被 push 到开发人员自己的代码仓库中。
  6. 然后,向“官方库”发起 pull request,并做 Code Review。
  7. 一旦通过,就向官方库进行合并。

这就是 GitHub 的工作流程。如果你有“官方库”的权限,那么就可以直接在“官方库”中建功能分支开发,然后提交 pull request。通过 Code Review 后,合并进 Master 分支,而 Master 一旦有代码被合并就可以马上 release。这是一种非常 Geek 的玩法。这需要一个自动化的 CI/CD 工具做辅助。是的,CI/CD 应该是开发中的标配了。

GitLab Flow

然而,GitHub Flow 这种玩法依然会有好多问题,因为其虽然变得很简单,但是没有把我们的代码和我们的运行环境给联系在一起。所以,GitLab 提出了几个优化点。

其中一个是引入环境分支,如下图所示,其包含了预发布(Pre-Production)和生产(Production)分支。

/images/2023-05/f86fa8b3f9da1980db576936534f26a0.webp

而有些时候,我们还会有不同版本的发布,所以,还需要有各种 release 的分支。如下图所示。Master 分支是一个 roadmap 分支,然后,一旦稳定了就建稳定版的分支,如 2.3.stable 分支和 2.4.stable 分支,其中可以 cherry-pick master 分支上的一些改动过去。

/images/2023-05/9457e374f32004a65b4829d17af133de.webp

这样也就解决了两个问题:环境和代码分支对应的问题;版本和代码分支对应的问题。

Ours后端协同工作流

以上的几个git工作流,都是业界主流的方案,没有那个绝对好,绝对坏,需要根据团队的情况选择.

我们后端团队根据实际情况, 设计了一套工作流方案,目前应用下来还比较丝滑,能够满足现阶段的开发需求.

我们的项目分为两类:

  1. 所有人共同开发的项目/多人共同开发的项目,如bff网关,后台网关等.
  2. 单人开发或2人开发的项目,如基础组件/单个rpc项目.

根据这两类项目,我们分为不同的开发发布流程.

  1. 所有项目都有4个固定的环境分支,生产环境,预发布环境,测试环境,开发环境.
  2. 每个环境都有自动化构建脚本,其中开发,测试通过commit触发(每次提交都执行一次构建),预发布和线上通过tag触发(打固定格式的tag会触发构建),构建后的产物上传到产物仓库.
  3. 开发和测试普通开发人员可以直接提交,预发布和生产必须通过提PR的形式,由审核人员审核代码才能合并.
  4. 多人项目执行GitFlow 协同工作流工作流, 每个人有自己的个人分支和共同的版本分支,大版本的时候所有版本代码都合并到版本分支上,再从版本分支合并到开发环境,测试环境,预发布环境,线上环境.
  5. 单人小项目,执行基本功能分支协同工作流,再开发分支上开发,依次合并到测试分支,预发布,线上.

以下是多人协作分支架构图: 多人项目分支流程.png

以下是开发流程图: 项目分支流程图.png

协同工作流的启示

通过以上的git工作流的比较和思考,会发现,没有绝对好的方案,只有适合的方案,每个团队有不同的开发习惯和版本发布周期, 所以选择工作流需要找到最适合团队情况的,并且要能满足需求的方案.

  1. 协同工作流不是玩好代码仓库的分支策略,而是基于分支策略保证我们软件的开发流程是高效且稳定的.
  2. 要相信流程,而不是相信人,代码的合并和编译构建,一定要让脚本去完成,而不是开发人员本地去构建.
  3. 工具很重要,磨刀不误砍柴工,拥抱工具,减少无意义的重复劳动.

参考

  1. 左耳朵耗子: https://time.geekbang.org/column/article/2440
0%