软件配置管理过程是贯穿整个软件开发周期的重要过程,为此,也诞生了许多著名的企业级工具,开源的CVS、SVN,企业级的ClearCase、PVCS。
由于财力有限,无法调研大型企业级软件,但CVS和SVN对于目前的软件开发,已显得不是那么的方便。在开源软件领域,开源协作的开发过程,采取的种种成熟的开发模式,却值得我们思考,于是我决定调研一下开源软件项目开发中的配置管理工具。
感谢本文的参考原文:
【git - 简明指南】
【一个成功的 Git 分支模型】
【Contributing to Open Source on GitHub】
Git本身并不能称之为一个完整的配置管理工具,但在开源领域,却是目前做的最好的版本管理工具。
Git的强大之处在于版本模型,采取的是直接记录快照的方式,简单明了。Git的版本管理类似于一个随时间变化的文件系统,每一个版本的具体内容,都会作为快照的一部分进行保存,这样的好处是,任意两个版本间都能快速的进行差异比较,了解代码直接的不同。
为了减少资源占用,如果文件并未发生变化,那么将不会被保存,而且其对文件的改动评估,是基于文件的指纹信息的,并非一般的系统时间戳,所以不会产生内容信息的不一致等错误。
另外我比较喜欢使用Git的一点,其大部分操作都是在本地执行的,效率非常的高,而且你在没有联网的情况下,依旧可以进行版本管理,如果你要回复到以前的一个版本,它立即就可以将你当前的文件变更为以前文件的快照,十分方便快捷。这样在很多情况下,都能轻松的工作。
开源软件一般喜欢在linux下开发,我也使用了ubuntu14.04,那么我将在此环境下说明git的使用方法
首先Git的安装很简单,只需在控制台下键入:
sudo apt-get install git
如果你需要git的GUI界面,那么还需要安装:
sudo apt-get install git-gui
Git是有工作路径的概念的,而我们的所有git指令,都作用于当前路径所处的工作空间,在一个目录下执行如下语句,将会将该目录初始化为一个Git工作空间:
git init
这时,我们的仓库目录中会自动的产生一个“.git”文件夹,这个文件夹中会保留有Git的临时文件以及本地仓库等
Git的工作空间大概是一个这样的结构:
在Git中,每一个版本库,都被称为一个仓库,仓库有本地和远程之分。Git初始化后,会为你构建一个本地仓库,HEAD指向当前的开发分支,还会建立一个缓冲区Stage,供你临时添加文件,构成一次commit。Stash则是一个工作状态保存栈,用于保存/恢复WorkSpace中的临时状态。
接下来,这个指令将添加文件到缓冲区中:
git add <file name>
当然,你也可以使用如下指令将一个目录的文件都添加到缓冲区:
git add <path>
如果你觉得缓存区中的文件已经适合提交到本地仓库中,称为一个新的版本了,那么你可以这样将新版本提交到本地仓库,当前工作的本地仓库即HEAD所指向的仓库,如果你的分支不对,可能需要分支切换:
git commit -m "commit message"
如果你有github账户,或者有一个远端仓库,那么你还可以将这份代码同步到远端仓库中,我们稍后会介绍如何在github上使用git同步代码。
分支是Git的一个非常有用的特性,有很多软件,在主要的框架写好后,会有隔离开发的需要,在那些经典的CVS/Subversion管理工具的世界中,合并/分支被认为是有些吓人的,而使用Git时,一切变得简单,而且Git正是鼓励你这样做,尽量通过分支的设置,使得代码开发流程更加的清晰。
分支是用来将特性开发绝缘开来的。在你创建仓库的时候,master 是“默认的”分支。下面我们将创建一个叫做“feature_x”的分支,并切换过去:
git checkout -b feature_x
切换回主分支:
git checkout master
要合并其他分支到你的当前分支(例如 master),执行:
git merge <branch>
但很不幸的是,不是所有的合并都不会带来冲突,如果两个人同时修改了一份代码,往往会造成难以合并,你需要手动修改冲突文件,然后将他们重新添加回来以保证合并成功:
git add <conflicts file name>
一个成功的分支模式大概像这样:
在很多情况下,我们往往不在意分支的管理,但这样往往会给开源项目带来种种问题,而一个设计合理的开源项目,往往可以很方便的多人协作来进行。
而下面我们将介绍一下,这个分支模型中,各个操作的流程和其对于开发过程的意义。
我们会发现,从Github上签下来的代码,基本上都能完美的直接构建运行,那么是如何维护开发版本的呢?
一般我们都会像这样,构建两个分支:
origin的master分支每个Git用户都很熟悉。平行的另外一个分支叫做develop分支。
我们认为master分支上的每个版本的代码,都是可发布的。而开发时切换到develop分支,在关键节点上,做好测试,确认无误后,将会和master分支合并,然后打上发布版本号的tag。对于这个操作,应该严格的把关,保障每个发行版的质量。
Feature分支(特性分支),是一种非常有用的辅助性分支,主要目标是帮助队员间并行开发,每个人应该在不同的分支开发自己辅助的新特性,这样能够让每个人的工作都是在一个非常明确的版本下进行。
如果不这样操作,带来的一个严重后果可能就是,某人的某个版本包含了未经测试的代码,而这份代码直接被提交到了develop分支中,那么所有人的工作在代码更新后,反而都出现了问题,全体员工都在debug,会严重影响项目的进度。
新建分支,这就像将当前版本的代码放进了一个安全的实现沙箱,即使带来问题,不会影响他人,但我们还是不推荐将自己的feature分支发布到公共代码库中,当然合作开发的时候除外。特性分支可以从develop分支拉取建立,最终必须合并会develop分支,只要特性还在开发,这个分支就应存在,但最终还是会被合并到develop中或被废弃。
Release分支是在新的版本快要发布时,核心团队应建立一个对应的Release-*分支,这个分支是用来在目前确定的软件特性下,不再添加新特性,全力修复已有bug,将软件调试好并进行最终测试,打包发布等工作。从develop分支拉取新的release分支的时间点是当开发工作已经达到了新版本的期望值。至少在这个时间点,下一版本准备发布的所有目标特性必须已经合并到了develop分支。其余不必要的特性可以先不合并,等特性测试无误,再合并入develop分支,以免增加发布前的测试和调试难度。
release分支创建好后,就确定了下一个版本号,以及该版本支持的新功能,我们可以在此更新软件的新功能列表,进行测试和小修小补,构建发布包和安装包等工作。
在一切工作都以完成后,我们会将release分支合并回master分支,然后打上tag标记
$ git checkout master
$ git merge --no-ff release-1.2
$ git tag -a 1.2
下面我们还需要将release分支的小修小改保存,那么需要将其合并至develop分支,但由于有些项目开发组还在工作,也可能更新了develop分支的代码,这步合并也有可能引入冲突。
$ git checkout develop
$ git merge --no-ff release-1.2
Hotfix分支往往也是临时的辅助分支,用来临时修复已有的问题,那么我们可以临时从一个有问题的发布版中,新建一个hotfix分支,这个分支在简单的修复bug后就会结束。
完成工作后,解决掉的bug代码需要合并回master分支,但同时也需要合并到develop分支,目的是保证在下一版中该bug已经被解决。当然,也有可能存在一些特殊情况,若当一个release分支存在时,hotfix 分支需要合并到release 分支,而不是develop分支,因为hotfix是紧急的,应该尽快被发布。
有一些很大型的软件,往往采取组件开发的方式,一个部件往往依赖一些别的部件,在他们开发的过程中,上下游的关系也是十分重要的。
Git可以很方便的添加自己关注的上游仓库:
git remote add pb git://github.com/reponame.git
你也可以方便的获取其最新版本
git fetch pb
同样,你需要同步到你的远端仓库中,才能使别人看到你的更改,使用命令git push [remote-name] [branch-name]
:
git push origin master
当然,你的更新不一定就成功,如果在你推送数据前,有其他人推送了更新,那么你的更新将会失败,你必须同步到最新版本,并与你当前的版本合并,你才能将该版本更新,同样,在github的协作模型中,也有类似的问题,你在发PR时,如果有其他人先更新了,那么你也要同步一下,你的更新才能被采纳。
在一些生产环境中,甚至连美工都有自己的远端仓库,她们会将自己的设计图上传到美工的仓库中,前端设计人员只要更新一下,就能知道她们是否有新的设计图样。
原文地址:http://blog.csdn.net/xfxyy_sxfancy/article/details/45291625