一个企业级项目是由多人合作完成的,不同开发者在本地开发完代码之后,可能提交到同一个代码仓库,同一个开发者也可能同时开发几个功能特性。这种多人合作开发、多功能并行开发的特性如果处理不好,就会带来诸如丢失代码、合错代码、代码冲突等问题。
所以,在编码之前,我们需要设计一个合理的开发模式。又因为目前开发者基本都是基于 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 页面的讨论,可以使开发者充分参与到代码的讨论中,有助于提高代码的质量,并且提供了一个代码变更的历史回顾途径。
那么,功能分支工作流具体的开发流程是什么呢?我们一起来看下。
$ git checkout -b feature/rate-limiting
2.在功能分支上进行代码开发,开发完成后 commit 到功能分支。
$ git add limit.go
$ git commit -m "add rate limiting"
3.将本地功能分支代码 push 到远程仓库。
$ git push origin feature/rate-limiting
4.在远程仓库上创建 PR(例如:GitHub)
进入 GitHub 平台上的项目主页,点击 Compare & pull request 提交 PR,如下图所示。
5.代码管理员收到 PR 后,可以 CR 代码,CR 通过后,再点击 Merge pull request 将 PR 合并到 master,如下图所示。
图中的“Merge pull request” 提供了 3 种 merge 方法:
通过分析每个方法的优缺点,在实际的项目开发中,我比较推荐你使用 Create a merge commit 方式。
从刚才讲完的具体开发流程中,我们可以感受到,功能分支工作流上手比较简单,不仅能使你并行开发多个功能,还可以添加 code review,从而保障代码质量。当然它也有缺点,就是无法给分支分配明确的目的,不利于团队配合。它适合用在开发团队相对固定、规模较小的项目中。接下来我们要讲的 Git Flow 工作流以功能分支工作流为基础,较好地解决了上述问题。
Git Flow 工作流是一个非常成熟的方案,也是非开源项目中最常用到的工作流。它定义了一个围绕项目发布的严格分支模型,通过为代码开发、发布和维护分配独立的分支来让项目的迭代流程更加顺畅,比较适合大型的项目或者迭代速度快的项目。接下来,我会通过介绍 Git Flow 的 5 种分支和工作流程,来给你讲解 GIt Flow 是如何工作的。
Git Flow 中定义了 5 种分支,分别是 master、develop、feature、release 和 hotfix。其中,master 和 develop 为常驻分支,其他为非常驻分支,不同的研发阶段会用到不同的分支。这 5 种分支的详细介绍见下表:
这里我们用一个实际的例子来演示下 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 步,你可以跟着以下步骤操作练习。
$ git checkout -b develop master
$ git checkout -b feature/print-hello-world develop
package main
import "fmt"
func main() {
fmt.Println("callmainfunction")
fmt.Println("Hello")
}
4 . 紧急修复 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. 恢复到修复前的工作状态
5 . 继续开发。
在 main.go 中加入 fmt.Println("Hello World")。 6 . 提交代码到 feature/print-hello-world 分支。
$ git commit -a -m "print 'hello world'"
7 . 在 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,如下图所示。
8 . code review 通过后,由代码仓库 matainer 将功能分支合并到 develop 分支。
$ git checkout develop
$ git merge --no-ff feature/print-hello-world
9 . 基于 develop 分支,创建 release 分支,测试代码。
$ git checkout -b release/1.0.0 develop
$ go build -v . # 构建后,部署二进制文件,并测试
10 . 测试失败,因为我们要求打印“hello world”,但打印的是“Hello World”,修复的时候,我们直接在 release/1.0.0 分支修改代码,修改完成后,提交并编译部署。
$ git commit -a -m "fix bug"
$ go build -v .
11 . 测试通过后,将功能分支合并到 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
12.删除 feature/print-hello-world 分支,也可以选择性删除 release/1.0.0 分支。
$ git branch -d feature/print-hello-world
亲自操作一遍之后,你应该会更了解这种模式的优缺点。它的缺点,就是你刚才已经体会到的,它有一定的上手难度。不过 Git Flow 工作流还是有很多优点的:Git Flow 工作流的每个分支分工明确,这可以最大程度减少它们之间的相互影响。因为可以创建多个分支,所以也可以并行开发多个功能。另外,和功能分支工作流一样,它也可以添加 code review,保障代码质量。
因此,Git Flow 工作流比较适合开发团队相对固定,规模较大的项目。
上面讲的 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),你可以跟着以下步骤操作练习。
访问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)
首先,要同步本地仓库的 master 分支为最新的状态(跟 upstream master 分支一致)。
$ git fetch upstream
$ git checkout master
$ git rebase upstream/master
然后,创建功能分支。
$ git checkout -b feature/add-function
在 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
在完成了开发,并 commit 后,需要将功能分支 push 到个人远程代码仓库,代码如下:
$ git push -f origin feature/add-function
提交到远程仓库以后,我们就可以创建 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 工作流基础上,解耦了个人远端仓库和项目远端仓库。
每种开发模式各有优缺点,适用于不同的场景,我总结在下表中:
总的来说,在选择工作流时,我的推荐如下:
本文由哈喽比特于2年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/s6LUiCg-FDT55eyiPycFJA
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。