一个成功的Git分支模型

自从博客搭起来,迟迟没有写东西。

通过一直关注的锤子科技,了解到国内软件开发这个江湖,有池建强这样一号人,
随之了解到MacTalk,竟发现自己会欣赏加佩服池老师这种人。

前日深夜,泊洲兄发了一份深夜福利
并说:我们把他翻译过来吧。我想,是时候动起来了。

万一自己真的像初中语文老师说的那样,将来我可以成为一个文豪呢~

福利是一篇外国人写的关于Git分支管理的文章,原名为A successful Git branching model
推荐做开发的伙伴阅读一下。

以下内容是基于版本控制工具Git展开的,最开始接触版本控制工具,用的是TortoiseHg,
用了一段时间Git后,赶脚还是Git好一些。

推荐一份Git教程

以下是我对原文的翻译,不足之处欢迎指出:

分布而集中

该分支模型有一个真正意义上的中央仓库,并且这个中央仓库是唯一的。

(Git本身是分布式版本控制系统,在技术层面上,是没有中央仓库这个说法的。)

我们称这样的一个中央仓库为origin。所有的Git用户对origin这个名字都应该比较熟悉的。

中央仓库

在一个项目的开发team中,每个开发者,都可以从origin获得(pull)资源,同时也能推送(push)到origin。

此外,每个开发者可以从其他开发者那里获得资源,以此组建一个开发小组。

例如,当我们和其他人一起协作开发一个大的新功能时,在提交自己的改动到中央仓库origin之前,

我们需要自己所在小组内部能够互相协作,这将是十分有用的。

上图中,Alice和Bob是一个小组,同时Alice和David是一个小组,Clair和David又是一个小组。

从技术实现上讲,这无非是在Alice的项目里,定义了一个指向Bot的远程链接而已

(git remote add bob git@bobserver bob.git),反之亦然。

主分支

中央仓库有2个主要的分支,这些分支将一直存在:

  • master
  • develop

主分支

所有Git用户都会知道中央仓库的master分支,与master分支并行的另外一个分支,我们称之为develop。

我们称origin/master为主要分支,因为分支的HEAD指向的源码总是反映了一个可以发布的产品状态(production-ready)。

我们称origin/develop为主要分支,因为分支的HEAD指向的源码,总是反映了下次发布前最新提交的开发代码。

有些人称之为“集成分支”(integration branch),因为我们的每晚自动构建都是基于此分支进行的。

(例如hudson,可以做自动构建工作)。

当develop分支的源码稳定并且准备发布,所有的改变应该合并(merge)到master分支,同时做一个发布版本的标签(tag)。

当每一次将develop所有更改合并回master时,将会产生一个新的可以发布的产品状态。

如果使用Git的hook来自动构建和转出最新代码到产品服务器上,那么develop合并到master上的操作一定要多加小心。

辅助分支

除了两个主分支之外,分支模型使用多种辅助分支来支持团队成员之间的并行开发、新功能的持续开发、

为产品发布做准备、快速修复产品线上的bug等。

与主要分支不同的是,辅助分支都有一个有限的生命周期,因为他们最终会被删除。

我们可能会用到的分支有:

  • 功能分支
  • 发布分支
  • 修补程序分支

每创建一个辅助分支都是有一个明确的目的。并且会严格规定该辅助分支是从哪个主分支fork过来的,

最终要merge到哪个分支上。

从技术角度来看,这些分支并没有特别之处。不过我们是从用途的角度来划分这些辅助分支的。

当然,这些分支都是从主分支fork过来的。

功能分支

可从哪个分支fork:

develop

必须合并回哪个分支:

develop

分支的命名规则:

除了master , develop , release-或hotfix-之外的任意名字

功能分支(主题分支)被用于开发即将到来的或遥远的未来版本的新功能。

功能分支

在创建一个功能分支进行开发时,该分支合并到develop分支的时间节点可能是不确定的,

但是最终会被合并到develop分支或者丢弃。

功能分支通常只存在于开发者本地的仓库,并不会被推送到远程(origin)。

当开发一个新功能时,从develop创建分支:

$ git checkout -b myfeature develop
Switched to a new branch "myfeature"

新功能开发完成后,将功能分支合并到develop分支,并将develop分支推送到远程。

$ git checkout develop
Switched to branch 'develop'

$ git merge --no-ff myfeature
Updating ea1b82a..05e9557
(Summary of changes)

$ git branch -d myfeature
Deleted branch myfeature (was 05e9557).

$ git push origin develop

发布分支

可从哪个分支fork:

develop

必须合并回哪个分支:

develop和master

分支的命名规则:

release-*

发布分支用来支持产品的更新。它允许最后一分钟的点缀我的和交叉T的。

此外,它允许修正一些小错误和准备即将发布版本的元数据(例如:版本号,构建日期等)。

在发布分支上做完以上工作,并将该分支合并到develop和master后,

develop分支就可以“干净的”等待新功能分支的到来了。

从develop分支创建一个发布分支的时间点为:在新的release版本即将发布之前,

develop分支达到了最理想的状态(所有本次更新要更新出去的新功能已经被合并到develop分支,

下一次发布的新功能还没有从release分支fork)。

在创建一个发布分支的刚开始,即将发布的分支才会被分配一个版本号。

在这个时刻之前,develop分支虽然已经反映了“下一个版本”的变化,但是自己并不知道

“下一个版本”最终会变为0.4还是1.0。

创建一个发布分支

发布分支从develop分支创建。例如,当前已经发布产品的版本号为1.1.5,该产品即将有一个大的更新。

develop分支已经准备好被更新出去并且我们决定新版本号为1.2。

$ git checkout -b release-1.2 develop
Switched to a new branch "release-1.2"

发布版本会存在一段时间,直至新版本更新到外网。在这段时间,fix bugs的工作在该分支上进行。

严禁在该分支上增加大的功能点。这种功能上的改动必须被merge到develop分支,等待下一次更新。

完成一个发布分支

当发布分支真正的可以发布时,还需要做两件事情。

第一,将该发布分支合并到master分支,并且要为这个merge做一个方便以后查看历史版本的tag。

$ git checkout master
Switched to branch 'master'

$ git merge --no-ff release-1.2
Merge made by recursive.
(Summary of changes)

$ git tag -a 1.2

第二,将该发布分支合并到develop分支。

$ git checkout develop
Switched to branch 'develop'

$ git merge --no-ff release-1.2
Merge made by recursive.
(Summary of changes)

当产品发布完成之后,删除发布分支:

$ git branch -d release-1.2
Deleted branch release-1.2 (was ff452fe).

修补程序分支

可从哪个分支fork:

master

必须合并回哪个分支:

develop和master

分支的命名规则:

hotfix-*

修补程序分支和发布分支非常相似,因为他们都是为一个新产品的发布做准备。

当线上产品出现严重bug,而此时develop分支尚不稳定时,我们就需要创建一个修补程序分支。

这样做的一个好处就是,当一个人准备修复线上产品的bug时,其他团队成员(在develop分支)可以继续工作。

创建修补程序分支

$ git checkout -b hotfix-1.2.1 master
Switched to a new branch "hotfix-1.2.1"

接下来开始fix bug,并进行一次或多次的commit

$ git commit -m "Fixed severe production problem"
[hotfix-1.2.1 abbe5d6] Fixed severe production problem
5 files changed, 32 insertions(+), 17 deletions(-)

fix bugs完成

$ git checkout master
Switched to branch 'master'

$ git merge --no-ff hotfix-1.2.1
Merge made by recursive.
(Summary of changes)

$ git tag -a 1.2.1

$ git checkout develop
Switched to branch 'develop'

$ git merge --no-ff hotfix-1.2.1
Merge made by recursive.
(Summary of changes)

唯一的例外是,当发布分支存在并且线上bugs可以等到发布分支的最终发布时再fix,

我们可以把修补程序分支合并到发布分支,不必再合并到develop分支。

$ git branch -d hotfix-1.2.1
Deleted branch hotfix-1.2.1 (was abbe5d6).
志遥 wechat
微信扫一扫,我在丁香园记公众号等你