07 | 工作流设计:如何设计合理的多人开发模式?

你好,我是孔令飞。今天我们来聊聊如何设计合理的开发模式。

一个企业级项目是由多人合作完成的,不同开发者在本地开发完代码之后,可能提交到同一个代码仓库,同一个开发者也可能同时开发几个功能特性。这种多人合作开发、多功能并行开发的特性如果处理不好,就会带来诸如丢失代码、合错代码、代码冲突等问题。

所以,在编码之前,我们需要设计一个合理的开发模式。又因为目前开发者基本都是基于 Git 进行开发的,所以本节课,我会教你怎么基于 Git 设计出一个合理的开发模式。

那么如何设计工作流呢?你可以根据需要,自己设计工作流,也可以采用业界沉淀下来的、设计好的、受欢迎的工作流。一方面,这些工作流经过长时间的实践,被证明是合理的;另一方面,采用一种被大家熟知且业界通用的工作流,会减少团队内部磨合的时间。在这一讲中,我会为你介绍4种受欢迎的工作流,你可以选择其中一种作为你的工作流设计。

在使用 Git 开发时,有4种常用的工作流,也叫开发模式,按演进顺序分为集中式工作流、功能分支工作流、Git Flow 工作流和Forking 工作流。接下来,我会按演进顺序分别介绍这 4 种工作流。

集中式工作流

我们先来看看集中式工作流,它是最简单的一种开发方式。集中式工作流的工作模式如下图所示:

A、B、C 为 3 位开发者,每位开发者都在本地有一份远程仓库的拷贝:本地仓库。A、B、C 在本地的 master 分支开发完代码之后,将修改后的代码commit到远程仓库,如果有冲突就先解决本地的冲突再提交。在进行了一段时间的开发之后,远程仓库 master 分支的日志可能如下图所示:

集中式工作流是最简单的开发模式,但它的缺点也很明显:不同开发人员的提交日志混杂在一起,难以定位问题。如果同时开发多个功能,不同功能同时往 master 分支合并,代码之间也会相互影响,从而产生代码冲突。

和其他工作流相比,集中式工作流程的代码管理较混乱,容易出问题,因此适合用在团队人数少、开发不频繁、不需要同时维护多个版本的小项目中。当我们想要并行开发多个功能时,这种工作流就不适用了,这时候怎么办呢?我们接下来看功能分支工作流。

功能分支工作流

功能分支工作流基于集中式工作流演进而来。在开发新功能时,基于 master 分支新建一个功能分支,在功能分支上进行开发,而不是直接在本地的 master 分支开发,开发完成之后合并到 master 分支,如下图所示:

相较于集中式工作流,这种工作流让不同功能在不同的分支进行开发,只在最后一步合并到master分支,不仅可以避免不同功能之间的相互影响,还可以使提交历史看起来更加简洁。

还有,在合并到 master 分支时,需要提交 PR(pull request),而不是直接将代码 merge 到 master 分支。PR 流程不仅可以把分支代码提供给团队其他开发人员进行 CR(Code Review),还可以在 PR 页面讨论代码。通过 CR ,我们可以确保合并到 master 的代码是健壮的;通过 PR 页面的讨论,可以使开发者充分参与到代码的讨论中,有助于提高代码的质量,并且提供了一个代码变更的历史回顾途径。

那么,功能分支工作流具体的开发流程是什么呢?我们一起来看下。

  1. 基于 master 分支新建一个功能分支,功能分支可以取一些有意义的名字,便于理解,例如feature/rate-limiting。
$ git checkout -b feature/rate-limiting
  1. 在功能分支上进行代码开发,开发完成后 commit 到功能分支。
$ git add limit.go
$ git commit -m "add rate limiting"
  1. 将本地功能分支代码 push 到远程仓库。
$ git push origin feature/rate-limiting
  1. 在远程仓库上创建 PR(例如:GitHub)。

进入 GitHub 平台上的项目主页,点击 Compare & pull request 提交 PR,如下图所示。

点击 Compare & pull request 后会进入 PR 页面,在该页面中可以根据需要填写评论,最后点击 Create pull request 提交 PR。

  1. 代码管理员收到 PR 后,可以 CR 代码,CR 通过后,再点击 Merge pull request 将 PR 合并到 master,如下图所示。

图中的“Merge pull request” 提供了 3 种 merge 方法:

  • Create a merge commit:GitHub 的底层操作是 git merge --no-ff。feature 分支上所有的 commit 都会加到 master 分支上,并且会生成一个 merge commit。这种方式可以让我们清晰地知道是谁做了提交,做了哪些提交,回溯历史的时候也会更加方便。
  • Squash and merge:GitHub 的底层操作是 git merge --squashSquash and merge会使该 pull request 上的所有 commit 都合并成一个commit ,然后加到master分支上,但原来的 commit 历史会丢失。如果开发人员在 feature 分支上提交的 commit 非常随意,没有规范,那么我们可以选择这种方法来丢弃无意义的 commit。但是在大型项目中,每个开发人员都应该是遵循 commit 规范的,因此我不建议你在团队开发中使用 Squash and merge。
  • Rebase and merge:GitHub 的底层操作是 git rebase。这种方式会将 pull request 上的所有提交历史按照原有顺序依次添加到 master 分支的头部(HEAD)。因为git rebase 有风险,在你不完全熟悉 Git 工作流时,我不建议merge时选择这个。

通过分析每个方法的优缺点,在实际的项目开发中,我比较推荐你使用 Create a merge commit 方式。

从刚才讲完的具体开发流程中,我们可以感受到,功能分支工作流上手比较简单,不仅能使你并行开发多个功能,还可以添加code review,从而保障代码质量。当然它也有缺点,就是无法给分支分配明确的目的,不利于团队配合。它适合用在开发团队相对固定、规模较小的项目中。接下来我们要讲的Git Flow 工作流以功能分支工作流为基础,较好地解决了上述问题。

Git Flow 工作流

Git Flow 工作流是一个非常成熟的方案,也是非开源项目中最常用到的工作流。它定义了一个围绕项目发布的严格分支模型,通过为代码开发、发布和维护分配独立的分支来让项目的迭代流程更加顺畅,比较适合大型的项目或者迭代速度快的项目。接下来,我会通过介绍Git Flow的5种分支和工作流程,来给你讲解GIt Flow是如何工作的。

Git Flow 的5种分支

Git Flow 中定义了 5 种分支,分别是 master、develop、feature、release和 hotfix。其中,master 和 develop 为常驻分支,其他为非常驻分支,不同的研发阶段会用到不同的分支。这5种分支的详细介绍见下表:

Git Flow 开发流程

这里我们用一个实际的例子来演示下Git Flow 的开发流程。场景如下:

a. 当前版本为:0.9.0。

b. 需要新开发一个功能,使程序执行时向标准输出输出“hello world”字符串。

c. 在开发阶段,线上代码有 Bug 需要紧急修复。

假设我们的 Git 项目名为 gitflow-demo,项目目录下有 2 个文件,分别是 README.md 和 main.go,内容如下。

package main

import "fmt"

func main() {
	fmt.Println("callmainfunction")
}

具体的开发流程有 12 步,你可以跟着以下步骤操作练习。

  1. 创建一个常驻的分支:develop。
$ git checkout -b develop master
  1. 基于 develop 分支,新建一个功能分支:feature/print-hello-world。
$ git checkout -b feature/print-hello-world develop
  1. feature/print-hello-world 分支中,在 main.go 文件中添加一行代码fmt.Println("Hello"),添加后的代码如下。
package main

import "fmt"

func main() {
	fmt.Println("callmainfunction")
	fmt.Println("Hello")
}
  1. 紧急修复 Bug。

我们正处在新功能的开发中(只完成了 fmt.Println("Hello")而非 fmt.Println("Hello World"))突然线上代码发现了一个 Bug,我们要立即停止手上的工作,修复线上的 Bug,步骤如下。

$ git stash # 1. 开发工作只完成了一半,还不想提交,可以临时保存修改至堆栈区
$ git checkout -b hotfix/print-error master # 2. 从 master 建立 hotfix 分支
$ vi main.go # 3. 修复 bug,callmainfunction -> call main function
$ git commit -a -m 'fix print message error bug' # 4. 提交修复
$ git checkout develop # 5. 切换到 develop 分支
$ git merge --no-ff hotfix/print-error # 6. 把 hotfix 分支合并到 develop 分支
$ git checkout master # 7. 切换到 master 分支
$ git merge --no-ff hotfix/print-error # 8. 把 hotfix 分支合并到 master
$ git tag -a v0.9.1 -m "fix log bug" # 9. master 分支打 tag
$ go build -v . # 10. 编译代码,并将编译好的二进制更新到生产环境
$ git branch -d hotfix/print-error # 11. 修复好后,删除 hotfix/xxx 分支
$ git checkout feature/print-hello-world # 12. 切换到开发分支下
$ git merge --no-ff develop # 13. 因为 develop 有更新,这里最好同步更新下
$ git stash pop # 14. 恢复到修复前的工作状态
  1. 继续开发。

在 main.go 中加入 fmt.Println("Hello World")

  1. 提交代码到 feature/print-hello-world 分支。
$ git commit -a -m "print 'hello world'"
  1. 在 feature/print-hello-world 分支上做 code review。

首先,我们需要将 feature/print-hello-world push 到代码托管平台,例如 GitHub 上。

$ git push origin feature/print-hello-world

然后,我们在 GitHub 上,基于 feature/print-hello-world 创建 pull request,如下图所示。

创建完 pull request 之后,我们就可以指定 Reviewers 进行 code review,如下图所示。

  1. code review 通过后,由代码仓库 matainer 将功能分支合并到 develop 分支。
$ git checkout develop
$ git merge --no-ff feature/print-hello-world
  1. 基于 develop 分支,创建 release 分支,测试代码。
$ git checkout -b release/1.0.0 develop
$ go build -v . # 构建后,部署二进制文件,并测试
  1. 测试失败,因为我们要求打印“hello world”,但打印的是“Hello World”,修复的时候,

我们直接在 release/1.0.0 分支修改代码,修改完成后,提交并编译部署。

$ git commit -a -m "fix bug"
$ go build -v .
  1. 测试通过后,将功能分支合并到 master 分支和 develop 分支。
$ git checkout develop
$ git merge --no-ff release/1.0.0
$ git checkout master
$ git merge --no-ff release/1.0.0
$ git tag -a v1.0.0 -m "add print hello world" # master 分支打 tag
  1. 删除 feature/print-hello-world 分支,也可以选择性删除 release/1.0.0 分支。
$ git branch -d feature/print-hello-world

亲自操作一遍之后,你应该会更了解这种模式的优缺点。它的缺点,就是你刚才已经体会到的,它有一定的上手难度。不过Git Flow工作流还是有很多优点的:Git Flow工作流的每个分支分工明确,这可以最大程度减少它们之间的相互影响。因为可以创建多个分支,所以也可以并行开发多个功能。另外,和功能分支工作流一样,它也可以添加code review,保障代码质量。

因此,Git Flow工作流比较适合开发团队相对固定,规模较大的项目

Forking 工作流

上面讲的Git Flow 是非开源项目中最常用的,而在开源项目中,最常用到的是Forking 工作流,例如 Kubernetes、Docker 等项目用的就是这种工作流。这里,我们先来了解下 fork 操作。

fork 操作是在个人远程仓库新建一份目标远程仓库的副本,比如在 GitHub 上操作时,在项目的主页点击 fork 按钮(页面右上角),即可拷贝该目标远程仓库。Forking 工作流的流程如下图所示。

假设开发者 A 拥有一个远程仓库,如果开发者 B 也想参与 A 项目的开发,B 可以 fork 一份 A 的远程仓库到自己的 GitHub 账号下。后续 B 可以在自己的项目进行开发,开发完成后,B 可以给 A 提交一个 PR。这时候 A 会收到通知,得知有新的 PR 被提交,A 会去查看 PR 并 code review。如果有问题,A 会直接在 PR 页面提交评论,B 看到评论后会做进一步的修改。最后 A 通过 B 的 PR 请求,将代码合并进了 A 的仓库。这样就完成了 A 代码仓库新特性的开发。如果有其他开发者想给 A 贡献代码,也会执行相同的操作。

GitHub中的 Forking 工作流详细步骤共有6步(假设目标仓库为 gitflow-demo),你可以跟着以下步骤操作练习。

  1. Fork 远程仓库到自己的账号下。

访问https://github.com/marmotedu/gitflow-demo ,点击fork按钮。fork 后的仓库地址为:https://github.com/colin404fork/gitflow-demo
2) 克隆 fork 的仓库到本地。

$ git clone https://github.com/colin404fork/gitflow-demo
$ cd gitflow-demo
$ git remote add upstream https://github.com/marmotedu/gitflow-demo
$ git remote set-url --push upstream no_push # Never push to upstream master
$ git remote -v # Confirm that your remotes make sense
origin	https://github.com/colin404fork/gitflow-demo (fetch)
origin	https://github.com/colin404fork/gitflow-demo (push)
upstream	https://github.com/marmotedu/gitflow-demo (fetch)
upstream	https://github.com/marmotedu/gitflow-demo (push)
  1. 创建功能分支。

首先,要同步本地仓库的 master 分支为最新的状态(跟 upstream master 分支一致)。

$ git fetch upstream
$ git checkout master
$ git rebase upstream/master

然后,创建功能分支。

$ git checkout -b feature/add-function
  1. 提交 commit。

在 feature/add-function 分支上开发代码,开发完代码后,提交 commit。

$ git fetch upstream # commit 前需要再次同步 feature 跟 upstream/master
$ git rebase upstream/master
$ git add <file>
$ git status
$ git commit

分支开发完成后,可能会有一堆 commit,但是合并到主干时,我们往往希望只有一个(或最多两三个)commit,这可以使功能修改都放在一个或几个commit中,便于后面的阅读和维护。这个时候,我们可以用 git rebase 来合并和修改我们的 commit,操作如下:

$ git rebase -i origin/master

第5讲已经介绍过了git rebase -i 的使用方法 ,如果你有疑问可以再去看看,这里不再说明。

还有另外一种合并 commit 的简便方法,就是先撤销过去 5 个 commit,然后再建一个新的:

$ git reset HEAD~5
$ git add .
$ git commit -am "Here's the bug fix that closes #28"
$ git push --force

squash 和 fixup 命令,还可以当作命令行参数使用,自动合并 commit。

$ git commit --fixup
$ git rebase -i --autosquash
  1. push 功能分支到个人远程仓库。

在完成了开发,并 commit 后,需要将功能分支 push 到个人远程代码仓库,代码如下:

$ git push -f origin feature/add-function
  1. 在个人远程仓库页面创建 pull request。

提交到远程仓库以后,我们就可以创建 pull request,然后请求reviewers进行代码 review,确认后合并到 master。这里要注意,创建pull request时,base通常选择目标远程仓库的master分支。

我们已经讲完了 Forking 工作流的具体步骤,你觉得它有什么优缺点呢?

结合操作特点,我们来看看它的优点:Forking工作流中,项目远程仓库和开发者远程仓库完全独立,开发者通过提交 Pull Request 的方式给远程仓库贡献代码,项目维护者选择性地接受任何开发者的提交,通过这种方式,可以避免授予开发者项目远程仓库的权限,从而提高项目远程仓库的安全性,这也使得任意开发者都可以参与项目的开发。

但Forking工作流也有局限性,就是对于职能分工明确且不对外开源的项目优势不大。

Forking工作流比较适用于以下三种场景:(1)开源项目中;(2)开发者有衍生出自己的衍生版的需求;(3)开发者不固定,可能是任意一个能访问到项目的开发者。

总结

这一讲中,我基于 Git 向你介绍了 4 种开发模式,现在跟我回顾一下吧。

  • 集中式工作流:开发者直接在本地 master 分支开发代码,开发完成后 push 到远端仓库 master 分支。
  • 功能分支工作流:开发者基于 master 分支创建一个新分支,在新分支进行开发,开发完成后合并到远端仓库 master 分支。
  • Git Flow 工作流:Git Flow 工作流为不同的分支分配一个明确的角色,并定义分支之间什么时候、如何进行交互,比较适合大型项目的开发。
  • Forking 工作流:开发者先 fork 项目到个人仓库,在个人仓库完成开发后,提交 pull request 到目标远程仓库,远程仓库 review 后,合并 pull request 到 master 分支。

集中式工作流是最早的Git工作流,功能分支工作流以集中式工作流为基础,Git Flow 工作流又是以功能分支工作流为基础,Forking工作流在Git Flow 工作流基础上,解耦了个人远端仓库和项目远端仓库。

每种开发模式各有优缺点,适用于不同的场景,我总结在下表中:

总的来说,在选择工作流时,我的推荐如下:

  • 非开源项目采用 Git Flow 工作流。
  • 开源项目采用 Forking 工作流。

因为这门课的实战项目对于项目开发者来说是一个偏大型的非开源项目,所以采用了Git Flow工作流。

课后练习

  1. 请你新建立一个项目,并参考Git Flow开发流程,自己操作一遍,观察每一步的操作结果。
  2. 请你思考下,在 Git Flow 工作流中,如果要临时解决一个 Bug,该如何操作代码仓库。

期待在留言区看到你的思考和分享,我们下一讲见!

精选留言

  • Geek_c3e438

    2021-06-08 11:31:29

    哈哈哈哈,上文刚说了commit规范,这篇就随意了,当然知道仅做演示,开个玩笑~
    作者回复

    是的,这里主要是演示工作流个演示。这里没有按commit message规范写的原因如下:
    1. 根据我的研发经验,很多时候,规范对大多数开发者是用来看的,所以如果制定了commit message规范,需要有相应的工具,来强约束大家遵守这个规范,因为是演示所以没搞这么复杂。
    2. IAM项目的commit 都是符合规范的,里面有工具强约束,可以看下。

    老哥看的很细,是个优化点,今后避免。

    2021-06-08 22:24:28

  • 张诚

    2021-06-09 19:38:50

    这章节给力,比外面专门讲git的教程看得还爽。
  • 💎A

    2021-06-08 08:56:42

    用source tree 一键git flow.
    作者回复

    牛批!

    2021-06-08 22:16:21

  • 我来也

    2021-07-05 19:56:20

    看的比较过瘾。

    这些git命令,我一般都用zsh里面git插件的缩写来完成。说白了就是一批alias命令。

    比如gcb切分支,gsta保存修改到堆栈,gstp恢复堆栈中的修改,gpsup新建远端分支。grb变基,grh 软重置,grhh硬重置等等。
    作者回复

    优秀!

    2021-07-10 01:30:13

  • byemoto

    2021-06-30 10:19:37

    如何保证develop和master分支不会产生冲突呢?
    作者回复

    他俩不会冲突的吧,有冲突在merge到develop的时候就解决了

    2021-07-03 08:46:33

  • NULL

    2021-08-11 08:03:35

    问题1,教程中是从develop分支创建的功能分支feature,那此时有新功能应该从哪里拉取,是dev还是master,如果新功能着急上线,从dev拉取就会上线其他功能的代码,就是功能分支什么情况从dev拉取什么情况从master拉取

    问题2,教程中,修复完bug后合并到dev和master,然后切到功能分支需要merge一下dev,那这样不也会把其他代码合并到当前功能分支吗,这个功能分先上线也会带上其他代码吧
  • forever_ele

    2021-08-06 00:02:24

    说一下我这边的Git工作流经验:我们会预设三个常驻分支,分别是 Prod-生产分支、Pre-Prod-预发布分支、Dev-开发分支,master保留分支未使用。当有新功能需要开发时,首先是从prod分支进行拉取个人开发分支,因为此时dev可能会有其他同学开发的其他需求代码,但实际发布时间未知,为了避免新功能发布时包含其他需求代码所以要从prod分支新建个人开发分支,保证分支是“干净的”。个人本地开发测试后 合并dev分支进行线上测试,没有问题再将分支合并至pre交付客户或非技术部门进行uat测试。最后将个人开发分支合并prod进行发布。
    作者回复

    流程很清晰呀

    2021-08-10 00:08:33

  • Alery

    2021-06-09 21:06:06

    请问Forking 工作流中git rebase upstream/master 这一步是做什么?
    作者回复

    合并master分支的代码,跟git merge相比,可以避免很多自动生成的merge记录

    2021-06-10 09:18:34

  • types

    2021-07-30 17:00:59

    看了git flow, tag都是在master上标记的,看起来只支持单个发行版本。
    如果我需要维护多个发行版本,多个发行版本有共性需求,也有各自的定制化需求,请问这个时候应该以 什么样的流程进行开发?
    作者回复

    tag是不区分branch的。

    比如你在develop分支打了v1.0.0 tag,切换到v1.0.0 tag时,git会自动切换到develop分支的v1.0.0 tag。

    如果要维护多个发行版,可以分多个repo,但不好管理。建议这么来:

    基础版本分支:
    master

    发行版A:
    masterA/feature/xxx
    masterA/develop

    发行版B:
    masterB/feature/xxx
    masterB/develop

    2021-07-31 07:09:04

  • 崔子昂

    2021-06-28 12:12:42

    很多公司会用Jira这种issue管理系统,而branch name用issue code的话,会有一些联动性的功能,比较纠结如果用功能名的话,就失去这个方便的地方了。
    作者回复

    可以根据需要自己指定branch名规范,如果有这种联动性需求,其实也可以适配

    2021-06-29 09:26:29

  • theseusv

    2021-06-08 17:09:03

    催更催更~
    作者回复

    我们加油

    2021-06-08 22:29:38

  • Juniper

    2021-09-24 16:55:41

    看完这篇文章,受益匪浅。不过有个疑问,如果采用git flow模式,提测的时候提release分支测试的,如果我有一个release1.0.0的分支在测试中,这个时候又有新的开发任务了,从develop分支切出来,此时的develop分支代码只经过开发测试,还非常不稳定,对于新的feature分支影响还是比较大的,怎么解决。严格安照串行的方式是没有问题的,release1.0.0验证完成,master develop merge完成发布,然后在开始进入下个功能的开发。但是现实场景很容易出现,上一个版本还是测试阶段,就有别的开发任务了
    作者回复

    好问题。

    等release1.0.0分支的修复合并到develop分支后,后来新建的分支再rebase下develop分支就可以了。

    2021-09-28 00:47:49

  • daz2yy

    2021-06-21 08:21:01

    老师好,GitFlow 工作方式,关于修复bug这里有点疑问,release分支修复bug,然后再合并到 develop 和 master;这里的 release 是只有这个feature的release吗?还是大家共用的一个 release 呢?如果是一个 feature 一个 release 那需要很多测试环境,如果大家共用一个 release,那会有其他的功能代码就不能在上面修复bug了
    作者回复

    release是这个feature的release,同时也是大家共用的。
    发版本是串行发布的,其它的后面排队

    2021-06-21 22:42:12

  • 惟新

    2021-06-08 15:33:51

    抓紧更新
    作者回复

    我们加油

    2021-06-08 22:28:07

  • OldFox

    2021-06-08 12:21:45

    git checkout develop
    git merge --no-ff hotfix/print-error # 6. 把 hotfix 分支合并到 develop 分支

    这两步,如果是同时有10个同事在开发十个feature,那就要通知那十个同事合并一下hotfix分支么。
    作者回复

    不用,合并hotfix分支是在develop和master 不是feature

    2021-06-08 22:27:57

  • Geek_c3e438

    2021-06-08 11:44:04

    1. 一般的开源项目对于Contributor而言并没有Write权限,所以是不是通常情况下不需要这句话:
    git remote set-url --push upstream no_push
    2. 在我们公司,各开发者一般都有Repository的Read权限,所以我们采用
    Forking工作流 + 精简版 Git Flow工作流
    作者回复

    1的理解是对的

    2021-06-08 22:26:01

  • Jone_乔泓恺

    2022-06-24 14:33:03

    老师您好,有几个问题想咨询下:
    文中 Git Flow 工作流中的第8点【code review 通过后,由代码仓库 matainer 将功能分支合并到 develop 分支。】
    1:这里的 matainer 是什么样的角色?
    2:合并到 develop 分支是在 Github 上进行的嘛?如果是,合并后的工作流是怎样的?比如如何通知开发人员,开发人员的本地如何更新 develop 分支?
    作者回复

    1. 代码仓库管理员
    2. GitHub和本地都可以。一般代码托管平台,在合并后会有邮件通知,但开发者可能很少关注。很多时候,这是由开发者开发习惯来保证的。例如:基于develop创建一个新分支时,要先pull 下远端的develop分支。push时有冲突时,也要先pull下远端的develop分支

    2022-12-18 08:55:18

  • JC

    2022-03-04 20:31:08

    git flow场景下是不是最新的release其实跟master是一样的,那master的意义是什么?
    作者回复

    master一直是最新的、稳定的、现网正在使用的代码。

    如果没有master会存在以下问题:
    1. 不能多版本并行开发(多版本并行开发的代码最终需要合并,往哪里合并?)
    2. 下一次发布时,需要知道上一次发布的具体版本号,新建release分支比较麻烦
    3. 还有其他一些弊端,你可以思考下

    2022-03-12 06:43:20

  • 愤怒的🦅

    2021-12-18 11:49:37

    有没有用到pre commit 这种fail fast机制提交前检测 好像还能规范commit msg格式
  • yandongxiao

    2021-11-23 00:21:56

    总结:
    基于 Git 工作流有四种:集中式工作流(只有一个master分支);功能分支工作流(master+feature);Git flow 工作流(master, develop, release, hotfix, feature);Forking 工作流(master+feature)。
    不论使用 Git flow 工作流,还是 Forking 工作流,都有压缩 commit 的需求;都需要与上游同步,Git Flow 使用 git merge --no-off,Forking 工作流使用 git rebase。