成功的GIT开发分支模型和策略

详细图文并茂以及git flow工具解释参考: http://danielkummer.github.io/git-flow-cheatsheet/index.zh_CN.htmlhtml

原文地址:http://nvie.com/posts/a-successful-git-branching-model/  git

本文中我将介绍我在多年的项目开发中使用的开发模型,这个模型被实践检验为正确有效的模式。本文中,我将不会涉及到项目的任何细节,只讨论关于分支策略和release管理
github

为何要使用Git?shell

网上有不少关于Git和集中式代码管理控制系统的比较,做为一个开发人员,我更喜欢Git,Git实际上颠覆了开发人员关于merge/branch的想法。从经典的CVS/SVN世界过来,merging/branching老是被认为是一个痛苦和使人胆寒的事情。可是在Git中,这些行为是很是简单和代价低廉的。好比在CVS/SVN的书籍中,branching和merging每每都在最后几章中讨论(专为高级用户所写),而在每一本Git的书籍中,这些merge/branch总在前三章中介绍(由于它们很基础)。app

正是源于这些操做在Git中简单,重复的特性,branching/merging再也不是一个使人生畏的事情。分布式

Decenteralized but cdentralized:工具

库做为中央“truth”repo.在Git中,虽然这个repo可能被认为是中央的repo,可是你要明白GIT是一个分布式的版本控制系统,也就是说从技术角度来讲没有这个central repo!咱们更确切地将这个central repo称为originpost

 

每一个开发人员pull/push to origin.可是除了中央式的pull/push关系,每个开发人员之间也可能从他们的子team之间pull changes。例如,对于两个或更多的开发人员同时工做在一个大的feature上,这种模型就更加有用了(特别是正在工做中的feature代码永久性push到origin前)。上面的图中,在alice和bob,alice和david,clair和david之间造成了subteam。ui

技术上说,实际上就是Alice定义了一个Git remote, 命名为bob,指向bob的repo,一样反之亦然。this

The main branches

核心上说,开发模型被已有的模型所启发,中央repo将永久保留两个主要的branches:

  • master
  • develop

origin上的master分支对于每个GIT用户来讲是很是熟悉的.和master branch平行的,有一个另外叫作develop的分支。

咱们考虑orgin/master做为main branch,这个分支上的HEAD老是反映了一个production-ready的状态;

咱们将origin/develop视做一个HEAD永远指示为了下一个release而最近递交的开发变化。有些人比较喜欢将此称为integration branch.在这个分支上,每日的build将从这里构建。

当在develop分支上的代码达到一个稳定状态点,达到能够发布的状态时,全部的变动都应该merge back到master,而且在master上tag一个release number。

这样每次当变动merge back到master时,这就是一个新的production release by definition.咱们更倾向于对此很是严格,所以理论上,咱们可使用一个Git hook sciprt实现每当有一个向master的commit,咱们自动构建和部署master上的软件到生产环境上去(由于master老是一个Production ready的状态)

Supporting branches:

除了main branches: master和develop,咱们的开发模型中也将使用一系列的supporting branches以便支持在team member之间实现并行开发,更加容易地实现feature的tracking,更方便地准备产品release,更好的辅助解决产品的问题。不像main branch(master,develop),这些branch老是有一个生命周期,由于他们最终将被删除。

咱们建议如下几种类型的分支:

  • feature branches;
  • release branches
  • hotfix branches

每种非main branch都有一个特定的目的,而且有严格的定义规则:这个分支应该从那个分支来建立,以及该分支最终的merge targets都有明确的定义。下面咱们将明确说明。

从技术角度来讲,这些branch自己并没有特别之处。这些branch的类型是由"how we use them"来分类的。他们就是简单的普通的Git branch.

Feature branches:

May branch off from: develop;

Must merge back into: develop;

Branch naming convention: 任何除了master,develop,release-*,hotfix-*以外均可以

Feature branch(或者被叫作topic branch)被用来为了即将到来的(upcoming)或者长远计划的release而作开发之用的。当开始开发一个feature时,这个feature的target release(目标release)在那时可能根本还肯定。feature branch的本质是:只要feature仍在开发中,它将一直存续,可是最终它将被merged back到dvelop分支(to definitely add the new feature to the upcoming release)或者被discarded(in case of a disappointing experiment)。

Feature branche典型地只存在于开发人员的repo中,并不在origin repo中存在。

当开始一个新的feature开发时,feature branch从develop branch中建立出来

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

结束的feature将被merged into the develop branch以便在即将到来的release中添加这个feature.

$ 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

--no-ff flag使得这个merge动做即使是这个merge属于fast-forward(no conflict)也总会产生一个新的commit object。这样就避免了关于曾近为了开发一个新的feature而作了feature branch并递交了多个文件的历史。

上图中,后一个fast-forward merge的场景,你将没法得知哪些commit objects最终造成了那个feature---你可能必须手动的查阅全部的log信息才能得知。一样在后一个场景中,你想rollback一个feature也是一个很是头疼的问题,然而若是咱们增长了--no--ff flag则很容易作到这些。

固然,使用--no-ff flag确实会产生一些多是空的commit objects,可是这个坏处相比其带来的好处是能够忍受的。

Release branches:

May branch off from: develop

Must merge back into: develop and master

Branch naming convention: release-*

注意release branch通常命名只包含major+minor,而不包含patch。好比release-1.0,release-2.3,对于release-1.5.1这样的tag只存在于hotfix生成的版本中

Release branches支持准备一个新的产品release而存在。They allow for last-minute dotting of i’s and crossing t’s.并且,他们容许晓得bug fix而且为那个release准备一些meta-data(好比version number, build dates,etc)。这些工做都在一个release branch上作,那么develop分支老是很清晰地准备为下一个大的release接受新的feature.

开始从develop branch off一个新的release branch的时机每每是在当develop基本反映了新的release的可接受状态时。至少全部的必须在这个release中deliver的feature必须被merge到了develop分支,这个时刻就是建立release branch的时机。全部为未来release计划的feature都不能merge下来直到上一个release branch已经被建立。

一般直到将要到来的release被赋予一个版本号,这将是这个release branch的一个起点。直到那个时刻,develop分支反映了下一个release的变化,可是关因而否那个下一个release会最终变成0.3或者1.0并非很清晰,直到release branch开始工做。这个决定在release branch 开始时决定下来,由项目的版本号命名规则来决定

Release branch由develop branch来建立。好比,版本v1.1.5是当前产品release,而咱们将有一个大的release将被release。develop分支的状态已经为下一个release作好了准备,而咱们决定这个release将命名为v1.2(而不是v1.1.6或者v2.0)。那么咱们能够branch off而且给这个release branch一个1.2的名称:

$ git checkout -b release-1.2 develop
Switched to a new branch "release-1.2"
$ ./bump-version.sh 1.2
Files modified successfully, version bumped to 1.2.
$ git commit -a -m "Bumped version number to 1.2"
[release-1.2 74d9424] Bumped version number to 1.2
1 files changed, 1 insertions(+), 1 deletions(-)

在建立一个新的release branch而且切换到该branch后,咱们bump the version number。这里bump-verison.sh是一个虚构的shell脚本,该脚本更改一些文件以便反映新的版本号变动。(这固然也能够是一个手工的变动)而后,这个bumped version number is commited.

这个新的branch可能会存续一段时间,直到这个release被正式rollout.在这个时间段内,bugfix可能会被应用到这个release branch上去(而不是应用到develop branch上去)。在这里增长大的新功能将被严格禁止。这些bugfix必须被merge到develop分支上去,这样又开始等待下一个大的release.

当releasea branch的状态真正达到实际可以release质量时,也须要作一些工做。首先,release branch须要merge到master(可能包含一些bug fix)(since every commit on master is a new release by definition, remember!)。接着,那个对master的commit必须被打上tag,以便该历史版本未来可以容易地被引用。最后,在release branch上作的bugfix变动须要被merge到develop上去,以便未来的release中包含这些bugfix。

前两步Git操做:

$ 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

 

release如今已经结束了,而且被打了标签1.2以便未来引用

为了将release branch上作的bugfix保持好,咱们须要将这些fix merge到develop分支上:

$ git checkout develop
Switched to branch 'develop'
$ git merge --no-ff release-1.2
Merge made by recursive.
(Summary of changes)

在这一步,咱们可能会碰到merge conflict(probably even, since we have changed the version number),若是发现conflict,则解决它而且commit掉

如今咱们确实完成了这个release的工做,release branch能够被删除了:

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

Hotfix branches:

May branch off from:

master

Must merge back into:

develop and master

Branch naming convention:

hotfix-*

 hotfix branch和release branch很是类似,由于他们自己也是用于为准备一个新的产品release而存在的(尽管是非计划的,每每由某个release现场发现紧急问题而触发的)。他们每每是由一个现场运行的产品release上报的问题来触发产生的。当一个critical bug必须立刻解决时,一个hotfix branch将从master branch中的相应tag版本处branch off出来。这样作的本质是:团队其余成员能够在develop branch上继续工做,而指定团队一我的在这个hotfix branch上准备一个快速产品fix版本。

hotfix branch由master branch来建立。好比,假设v1.2是当前报严重问题的产品release版本,可是因为在develp branch上的变动还不稳定,因此咱们开始从master上拉一个hotfix branch开始工做:

$ git checkout -b hotfix-1.2.1 master
Switched to a new branch "hotfix-1.2.1"
$ ./bump-version.sh 1.2.1
Files modified successfully, version bumped to 1.2.1.
$ git commit -a -m "Bumped version number to 1.2.1"
[hotfix-1.2.1 41e61bb] Bumped version number to 1.2.1
1 files changed, 1 insertions(+), 1 deletions(-)

不要忘记bump the version number after branching off~!

而后,fix the bug,commit the fix in one or more seperate commits:

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

Finishing a hotfix branch:

当完成该问题的fix时,bugfix须要merged back到master中去,同时也须要merge到develop branch中去,只有这样才能保证bugfix自己将会在下一个release中自动包含。这和release branch结束的动做是同样的。

首先,更新master而且tag the release:

$ 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

下一步,也须要同时包含bugfix到develop分支中去:

$ git checkout develop
Switched to branch 'develop'
$ git merge --no-ff hotfix-1.2.1
Merge made by recursive.
(Summary of changes)

在这里有一个例外的rule:当一个release branch当前存续,那么这个hotfix change须要merge到那个release branch中去,而不是develop分支。Back-merging the bugfix into the release branch will eventually result in the bugfix being merged into the develop too, when the release branch is finished, (If work in develop immediately requires this bugfix and cannot wait for the release branch to be finished, you may safely merge the bugfix into the develop now already as well.)

最后,删除这个临时的branch

$ git branch -d hotfix-1.2.1
Deleted branch hotfix-1.2.1 (was abbe5d6).

原创:在github上大型项目团队branch策略:

Summary:

虽然本篇文章自己对于分支策略并没有使人震惊之处,可是那个big picture图片确实对咱们的项目成功有很是重要的意义。它构建了一个优雅地心智模型,而该模型易于理解而且容许团队充分理解整个产品的branching/releasing流程。

 两个team member有两个repo,互为remote,当git push时,有可能出现conflict,这时须要作的事情是必须先git pull操做,解决冲突之后,再作git push。这和在一个repo时merge冲突是相似的。

https://github.com/nvie/gitflow 是一个对git扩充的flow惯例,很是实用

相关文章
相关标签/搜索