分支策略总结
前几日在发布新版本时,发现 SVN 的分支策略有问题,然后读了 SVN 的常见分支模式,依照文章里的模式改变了分支策略,貌似解决了问题。但我对之前用的策略还是念念不忘,经过调查和思考,得出结论:之前用的策略也没有问题,and what’s more,那是 Git 更常用的分支模式,但更适合于开发流程规范、并严格遵循的项目。
在 Git 分支模型的阐述上,Vincent Driessen 的 A successful Git branching model 是一篇很多人认为不错的文章,译文也已经有好几篇了:介绍一个成功的 Git 分支模型,Git 分支的最佳实践,一个成功的Git分支模型。
个人认为,这篇文章阐述的分支模型是非常不错的,但遣词造句上实在有些繁琐,读起来很费劲,不过绝对值得一读。
下面是我对分支策略的总结。
Subversion 和 Git
- Git 是分布式的版本控制系统,所有人都拥有一个仓库,而不仅仅是一个 working copy。但依然要有一个远端的中心,称为 origin。相对的,Subversion 是集中式的版本控制系统,仓库只在远端。
- Subversion 的三大部分是 trunk、branches、tags,即主干、分支、标记。相对的,Git 没有 trunk 的概念,主干可以认为是 master 分支,也是分支之一。
- Git 的分支才是真正意义上的分支。相对的,Subversion 在本质上不存在分支,所谓分支只是目录的拷贝。
- Git 在分支与合并方面是简单易行的。相对的,Subversion 的分支与合并总是让人恐惧。
分支模式一(Git 风格)
- 长期分支有主分支(master)和开发分支(develop),短期分支有特性分支(feature)、预发布分支(release)、补丁分支(hotfix)。
- master 分支,始终 仅 保存每次发布的版本,HEAD 则指向当前发布的最新版本。日常的开发工作不直接在主分支进行。
- develop 分支,其中为 下一次 要发布的版本(而不包含下次的下次发布应包含的功能)。
- feature 分支,开发某项新特性时使用。这项特性可能在下一次发布时加入软件,也可能在下次的下次发布时才加入软件。也有可能是实验性质的特性,最终可能得以加入软件,也可能效果不好直接抛弃。它应从 develop 分支出,开发完毕后合并回 develop 或直接丢弃。注意并回的时机,是要在 下次发布的版本 中引入这个特性时,而 不是 下次的下次发布时。合并完毕后,应将这个 feature 分支删除。
- release 分支,在某一版本准备发布时使用。在 develop 分支已经可以进入发布前的测试时,从 develop 分支出,命名为
release-1.0
。测试过程中的 bug 修复,应提交到该分支。测试结束可以发布时,将该分支合并回 master 分支和 develop 分支,并给 master 分支打一个 tag(如 1.0)。然后,将这个 release 分支删除。需要注意的是,合并回 master,是因为这将成为一个新的发布版本;合并回 develop,是为了将 release 分支中对 bug 的修复也合并回 develop 分支,更好的方式是随着测试而不断地将 bug 修复合并回 develop,避免最后才一次性合并。 - hotfix 分支,在线上版本出现 bug 需要紧急修复时使用。在 master 分支出,命名为
hotfix-1.0.1
。在完成修复代码并通过测试后,合并回 master 和 develop,并对 master 打一个 tag(如 1.0.1)。然后,将这个 hotfix 分支删除。
分支模式二(Subversion 风格)
- trunk 主干,日常的开发工作直接在 trunk 进行。
- 长期分支有发布分支(release),短期分支有特性分支(feature)。
- release 分支,在某一版本准备发布时使用。在 trunk 中的开发已经可以进入发布前的测试时,从 trunk 分支出,命名为
release-1.0
。测试过程中的 bug 修复,应提交到该分支。测试结束可以发布时,将该分支合并回 trunk,并给该 release 分支打一个 tag(如 1.0)。注意,这个 release 分支将 永久保留 ,之后的 hotfix 也将在此分支进行。 - feature 分支,开发某项新特性时使用。这与分支模式一里的 feature 分支完全相同,唯一不同的是,它从 trunk 分支出,并最终合并回 trunk 或直接丢弃,最后被删除。
Then which one?
根据实际情况。
对于开发流程规范的团队,采用第一种分支模式应该会更好,尤其对于较大的项目,优势更加明显。
第二种分支模式的最大优势在于简单,团队的学习成本较低。除此之外,除了可以清晰方便地维护所有发布出去的版本,也没别的优势了。朴素的第二种分支模式是有劣势的,最明显的是 trunk 可能经常处于不稳定、甚至无法通过 Build 的状态。可以对第二种分支模式附加一些约束,比如必须保证向 trunk 的每次提交都是至少可 Build 的,来避免这些劣势可能带来的影响。
另外,分支模式与使用 Git 还是 Subversion 无关。无论使用哪一种版本控制工具,都可以采用任一种分支模式。只不过,如果用 Subversion 而采用第一种分支模式,那实际执行起来应该比较恶心,不如使用 Git 更轻松。
后附
第一种模式来源于文章开头提到的 Vincent Driessen 的 A successful Git branching model,下面为原文中的示意图。
第二种模式来源于 Version Control With Subversion(Ben Collins-Sussman, Brian W. Fitzpatrick, C. Michael Pilato)。