文中我会展示一种开发模型,一年前该模型就已经被我用在所有的项目中(包括工作中的项目和私有项目),结果是非常成功的。我早就想为此写点东西,可直到现在才有时间。本文不会讲述任何项目的细节,只会涉及到分支策略和发布管理。
为什么是Git?
要全面了解Git与其它集中式版本控制系统相比的优劣,可以参考这个页面。这方面的争论可谓是硝烟弥漫。作为一个开发者,所有这些工具中我最钟情于Git。Git的的确确改变了人们考虑合并及分支的方式。在我之前所处的经典CVS/Subversion世界中,合并/分支总是被认为是有点可怕的事情(“小心合并冲突,丫会恶心到你”),因此你只应偶尔干这种事情。
但有了Git,这类事情就变得非常简单,分支及合并甚至被认为是你日常版本控制操作的核心之一。例如,在CVS/Subversion的书中,分支及合并往往在后面的章节才被介绍(针对高级用户),但在每一本Git的书中,该内容已经在前3章中介绍(基础)。
简单及易重复性带来的好处就是,分支及合并变得不再可怕。版本控制工具本该帮助我们方便的进行和分支及合并操作。
简单介绍下工具后,让我们来看开发模型。我讲介绍的模型本质上只是一组步骤,每个团队成员都必须遵循这些步骤以形成一个可靠管理的软件开发过程。
去中心化但仍保持中心化
在这个分支模型中我们使用的,且被证实工作得很好的仓库配置,其核心是一个中心“真理”仓库。注意只有该仓库才被认为是中心库(由于Git是DVCS [分布式版本控制系统],在技术层面没有中心库这一东西)。之后我们用origin指代该仓库,因为大多数Git用户都熟悉这个名称。
每个开发者都对origin做push和pull操作。不过除了这种中心化的push-pull关系外,每个开发者还可以从其他开发者或者小组处pull变更。例如,可能两个或更多的开发者一起开发一个大的特性,在往origin永久性的push工作代码之前,他们之间可以执行一些去中心化的操作。在上图中,分别有Alice和Bob、Alice和David、Clair和David这些小组。
从技术上来说,这仅仅是Alice定义一个Git remote,名字为bob,指向Bob的仓库,反过来也一样。
主要分支
master
develop
每个Git用于都应该熟悉origin上的master分支。与master分支平行存在的,是另外一个名为develop的分支。
我们认为origin/develop分支上的HEAD源码反映了开发过程中最新的提交变更。有人会称之为“集成分支”。该分支是自动化每日构建的代码源。
当develop分支上的源码到达一个稳定的状态时,就可以发布版本。所有develop上的变更都应该以某种方式合并回master分支,并且使用发布版本号打上标签。稍后我们会讨论具体操作细节。
因此,每次有变化被合并到master分支时,根据定义这就是一次新的产品版本发布。我们趋向于严格遵守该规范,所以理论上来说,每次master有提交时,我们都可以使用一个Git钩子(hook)脚本来自动构建并部署软件至产品环境服务器。
支持性分支
紧接着主要分支master和develop,我们的开发模型使用多种支持性分支来帮助团队成员间实现并行开发、追踪产品特性、准备产品版本发布、以及快速修复产品问题。与主要分支不同的是,这些分支的寿命是有限的,它们最终都会被删除。
我们会用到的分支有这几类:
特性分支(feature branch)
发布分支(release branch)
热补丁分支(hotfix branch)
上述每种分支都有特定的用途,它们各自关于源自什么分支、合并回什么分支,都有严格的规定。稍后我们逐个进行介绍。
从技术角度来说,这些分支一点都不“特殊”。分支按照我们对其的使用方式进行分类。技术角度它们都一样是平常的Git分支。
特性分支
必须合并回:develop
分支命令约定:任何除master, develop, release-*, 或 hotfix-*以外的名称
特性分支(有时也被称作topic分支)是用来为下一发布版本开发新特性。当开始开发一个特性的时候,该特性会成为哪个发布版本的一部分,往往还不知道。特性分支的重点是,只要特性还在开发,该分支就会一直存在,不过它最终会被合并回develop分支(将该特性加入到发布版本中),或者被丢弃(如果试验的结果令人失望)。
特性分支往往只存在于开发者的仓库中,而不会出现在origin。
创建一个特性分支
开始开发新特性的时候,从develop分支创建特性分支。
$ git checkout -b myfeature develop
Switch to a new branch “myfeature”
合并完成的特性回develop
完成的特性应该被合并回develop分支以将特性加入到下一个发布版本中:
$ git checkout develop
Switch 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标记会使合并永远创建一个新的commit对象,即使该合并能以fast-forward的方式进行。这么做可以避免丢失特性分支存在的历史信息,同时也能清晰的展现一组commit一起构成一个特性。比较下面的图:
原文转自:http://www.juvenxu.com/2010/11/28/a-successful-git-branching-model/