在这篇文章中,我将概括我在大约一年前提出的一些项目(工作和私人项目)中使用的开发模型,并取得了非常成功的结果。一段时间以来,我一直渴望写作和分享,但直到现在我才抽出时间去做。我不会涉及任何项目细节,只是分支策略和发布管理。为什么要使用git?有关Git与集中式源代码控制系统的优缺点的讨论,请参阅此网站。这里有很多很棒的、激烈的辩论。作为一名开发人员,这些天我更喜欢使用Git。Git确实改变了开发人员考虑合并和分支的方式。我来自传统的CVS/Subversion世界,在那里合并/分支是一件可怕的事情(“当心合并冲突,它们会反噬你!”),而且人们只会偶尔这样做。但有了Git,这些操作变得轻而易举,它们将成为你日常工作流程的核心部分。例如,在CVS/Subversion手册中,分支和合并直到最后一章才第一次出现(仅供高级用户参考),但在每本Git手册中,第3章(基本上)都涵盖了。使用简单且可重复的基因,分支和合并不再是问题。版本控制工具应该专注于分支/合并,而不是其他。工具说完了,那么我们就可以开始进入开发模型了。我要介绍的开发模型只是每个团队成员在进入软件开发过程之前必须遵循的规范。这种基于“真正的”中央存储库的去中心化和集中化的分支模型使我们能够很好地协同工作。请注意,此存储库仅被视为中央存储库(因为GIT在技术上没有中央存储库)。我们将此存储库命名为origin,因为Git用户都知道它。所有开发人员都从原始存储库中提取代码或将代码推送到原始存储库。除了中心化的推拉关系,开发者还可以从其他开发者库中拉取代码变更。例如,为了开发一个大特性,多个开发人员组成一个开发团队,开发过程不必在特性完成之前推送到源站。在上图中,Alice和Bob、Alice和David以及Clair和David之间存在团队。在技??术层面,Alice需要在本地库中添加一个远程Git分支,并命名为bob,指向Bob的仓库。其他人也一样。主分支git的核心在开发模式上很大程度上受到了现有模型的启发。中央仓库在整个生命周期中维护两个主要分支:masterdevelop每个Git用户都熟悉origin中的master分支。与master分支平行的是另一个名为develop的分支。我们称origin/master为主分支,该分支源代码的HEAD始终指向生产环境可以使用的状态。我们称origin/develop为主分支,这个分支源代码的HEAD总是反映下一个版本的最新开发状态。有人称这个分支为“集成分支”。所有日常自动构建都是从这里构建的。当develop分支上的源代码达到稳定点并准备好发布时,所有更改都应该以某种方式合并回master分支,然后标记为发布版本。接下来将详细讨论这是如何完成的。因此,每次将更改合并回master分支时,根据定义,它就是一个新的生产版本。我们倾向于对此非常严格,所以理论上我们可以使用Git钩子脚本在每次提交到master分支时自动构建和发布我们的软件到生产服务器。辅助分支在讨论完master分支和develop分支后,接下来要讨论的各种辅助分支支持成员间并行开发,轻松跟踪功能开发,发布生产版本,快速修复生产环境产生的bug。与主分支不同,辅助分支的生命周期有限,通常在完成任务后被删除。可能的辅助分支分类有:功能分支发布分支错误修复分支每个分支都有一个特殊的用途。这些分支起源的分支和它们合并回的分支都是严格定义的。我们稍后会详细讨论。从技术上讲,辅助分支没有特殊含义。我们根据具体的使用功能对辅助分支进行分类。辅助分支与普通的Git分支没有什么不同。功能分支功能分支可能源自:开发分支功能分支必须合并回:开发分支功能分支命名约定:任何名称都可以,但master、develop、release-*或hotfix-*除外。功能分支(或功能分支)用于开发即将或稍后发布的新功能。当一个功能分支创建后开始开发时,它稍后将被合并的点是未知的。功能分支的本质是它与开发过程一起存在,但保证会被合并回开发(明确在下一个预期版本中添加新功能)或丢弃(以防实验结果不佳).特性分支通常存在于开发者的仓库中,不会出现在原始仓库中。创建一个特性分支当我们开始编写一个新特性时,请切换出开发分支$gitcheckout-bmyfeaturedevelop切换到一个新分支“myfeature”在开发过程中添加已完成的特性已完成的特性可能会合并到开发分支以确保它们添加到即将发布的版本中$gitcheckoutdevelop切换到分支'develop'$gitmerge--no-ffmyfeatureUpdatingea1b82a..05e9557(更改摘要)$gitbranch-dmyfeatureDeletedbranchmyfeature(原为05e9557)。$gitpushorigindevelop–no-ff标志将在合并分支时创建一个新的提交对象,即使可以使用fast-forwark方法提交合并。这样可以避免丢失功能分支的历史信息,可以将所有的功能一起提交。请看图片对比:在后一种情况下,无法从Git历史中查看提交对象在哪些地方它们共同实现了一个功能——您必须手动读取所有日志消息。在后一种情况下,还原整个功能(即一组完整的提交)确实令人头疼,但可以使用--no-ff标志轻松完成。当然,虽然它创建了更多的空提交对象,但收益远远大于成本。发布分支该分支可能源自:develop分支必须合并到:develop和master分支分支命名约定:release-*发布分支(Releasebranches)支持新产品发布的准备。他们允许在最后一刻追查细节。此外,它们还允许修复小错误以及为发布准备元数据(版本号、构建日期等)。在发布分支上完成所有工作后,开发分支将被清除以接收下一个主要功能发布。从开发分支签出新发布分支的重要时刻是开发(基本上)反映了新版本的预期状态。至少,在这一点上,所有针对待构建版本的功能必须合并回开发分支。未来版本的所有功能可能不会-他们必须等到发布分支被检出才能这样做。在发布分支的开始,即将发布的版本被分配了一个版本号——一个前所未有的版本号。在那一刻之前,开发分支反映了“下一个版本”的变化,但在发布分支开始之前,“下一个版本”最终将成为0.3版还是1.0版仍然不清楚。这个决定是在发布分支开始时做出的,并由项目关于版本号提升的规则强制执行。创建发布分支发布分支是从开发分支派生出来的。例如,假设我们当前的产品版本是1.1.5,即将发布一个新的主要版本。develop分支已为“下一个版本”做好准备,我们决定将版本号更改为1.2(而不是1.1.6或2.0)。所以,我们所要做的就是检查发布分支并给它一个反映版本号的名称:$gitcheckout-brelease-1.2developSwitched切换到一个新分支“release-1.2”$./bump-version.sh1.2文件修改成功,版本升级到1.2.$gitcommit-a-m"Bumpedversionnumberto1.2"[release-1.274d9424]Bumpedversionnumberto1.21文件更改,1次插入(+),1次删除(-)之后creation创建一个新的分支并切换到它之后,我们需要修改版本号。在此示例中,bump-version.sh是一个虚构的脚本文件,它更改工作副本中的某些文件以反映新版本。(当然手动也可以,重点是那些改动过的文件)然后,提交碰撞后的版本号。新分支将存在,直到发布版本被确认。同时,错误修复可能会应用到这个分支(而不是开发)。严禁向该分支添加大型新功能。这些分支必须合并回开发分支,然后等待下一个主要版本。完成并发布您的分支当您真的准备好发布您的分支时,您还需要做一些其他的事情。首先,release版本要合并到master分支(一定要保证每次提交到master分支的都是最新版本)。接下来一定要将更新记录标记到master分支,以备日后查看此版本时参考。最后,对发布分支所做的更改需要重新合并到开发分支中,以确保未来的版本也修复这些错误。在Git中执行以下两步:$gitcheckoutmasterSwitchedtobranch'master'$gitmerge--no-ffrelease-1.2Mergemadebyrecursive.(Summaryofchanges)$gittag-a1.2到目前为止,这个版本已修订并用作未来的参考版本。注意:您可能还想使用-s或-u
