- 引言
- 本书涉及的内容
- 第 1 部分 Python 开发入门
- 第 1 章 Python 入门
- 第 2 章 开发 Web 应用
- 第 3 章 Python 项目的结构与包的创建
- 第 4 章 面向团队开发的工具
- 第 5 章 项目管理与审查
- 第 6 章 用 Mercurial 管理源码
- 第 7 章 完备文档的基础
- 第 8 章 模块分割设计与单元测试
- 第 9 章 Python 封装及其运用
- 第 10 章 用 Jenkins 持续集成
- 第 11 章 环境搭建与部署的自动化
- 第 12 章 应用的性能改善
- 第 13 章 让测试为我们服务
- 第 14 章 轻松使用 Django
- 第 15 章 方便好用的 Python 模块
- 附录 A VirtualBox 的设置
- 附录 B OS(Ubuntu)的设置
6.6 考虑实际运用的 BePROUD Mercurial Workflow
多人合作进行开发时,难免会遇到几个本地环境之间的提交出现矛盾,以及为解决矛盾需要进行合并的情况。另外,在多种功能同时进行开发的过程中,很可能后实现的功能需要先发布。为防止这类情况给团队开发带来混乱,保证开发和发布的顺利进行,我们必须事先确定好版本库创建分支与合并分支的时机。
另外,我们的理想情况是所有工作人员都可以通过命令行对版本库进行操作,但有些时候受条件所限并不能满足这一要求。为在这种情况下也能保证工作进度,我们需要用到一些工具,这些工具也会在本部分进行介绍。
6.6.1 概述
这里将介绍的是我们自己使用 Mercurial 进行源码管理的工作流程和管理结构。我们将在讲述项目相关人员以及开发方法等背景的基础上,为各位说明工作流程的相关内容。
NOTE
本节内容以 bpmercurial-workflow 文档为基础。文档与源码的许可证为 CC6 BY 2.1。本节讲述的流程与 Web 版相同,只是为了方便阅读对结构和文章作了少量修改。
bpmercurial-workflow 文档
http://beproud.bitbucket.org/bpmercurial-workflow/ja/
CC BY 2.1
https://creativecommons.org/licenses/by/2.1/au/
6 Creative Commons,简称 CC,中国大陆正式名称为知识共享,是一个非营利组织,也是一种创作的授权方式。此组织的主要宗旨在于增加创意作品的流通可及性,作为其他人据以创作及共享的基础,并寻找适当的法律以确保上述理念。——编者注
6.6.2 背景
既然要说明工作流程,那自然少不了项目的背景。所以我们先来了解一下背景。
◉ 目标项目
在这个工作流程中我们的目标项目是开发应用于 B to C 的 Web 站点(包括系统在内)。
多个小开发任务(包括设计变更等)并行进行,支持发布顺序不定的情况。
源码等成品的交付工作,均通过 Mercurial 向客户管理的版本库(后述的发布版本库)进行 push。
◉ 这个工作流程的相关人员
○ 程序员
提交系统的源码,主要负责管理版本库的人员。分支的合并与切换也由程序员负责。
服务器上已经为成员准备了各自的用户账户。为方便说明,我们这里假设程序员的用户名为 programmer。
○ 设计师
提交 HTML 模板、各种媒体文件的人员。也可能是网页制作工程师。
设计师需要向服务器上传文件,所以也备有用户账户。
○ 客户
接受开发完成的源码等成品的人员。通过后述的发布版本库取走源码。
◉ 工作环境
程序员和设计师对源码进行修改、测试等工作的环境,即服务器或本地机器上的环境。
本书中,我们将在给开发专设的服务器(Linux)上对版本库进行操作。至于设计师工作的服务器环境,我们也已经保证该环境能启动应用程序服务器来查看模板文件等是否正常工作。以 Python/Django 为例来说,就是用 runserver 等来负责启动。
6.6.3 版本库的结构
我们使用的是分布式版本控制系统,所以必须掌握版本库的结构以及各版本库的作用(图 6.14)。
图 6.14 版本库的结构
◉ 主版本库(master)
包含所有成果的版本库。用来积累以及共享整个团队每天开发出来的成果(比如开发中的分支等)。
版本库路径示例:/var/hg/example-prj
◉ 发布版本库(release)
装有已完成开发且等待发布到生产环境中的源码。放入这个版本库中的代码就是我们交给客户的成品。客户会使用这个版本库中的代码进行部署等工作。一般只有 default 分支处于活动状态。
进行发布(交付)工作时,我们要把 default 分支从主版本库 push 到发布版本库。
版本库路径示例:/var/hg/example-prj-release
◉ 工作版本库(working)
进行源码添加及修改等工作的版本库。开发成果要先提交到这个版本库,然后再 push 到主版本库。获取其他人的开发成果时,要从主版本库 pull 到这个版本库。
工作版本库既可以在服务器上也可以在本地环境上。
由于本书所介绍的开发将在服务器上进行,所以我们将主版本库 clone 至工作人员在服务器上的主目录下。
版本库路径示例:/home/programmer/example-prj。
6.6.4 提交源码
源码写好后要提交到工作版本库。
default 分支要时常用于发布,所以在提交成果时,除了为发布而进行合并以外都要使用其他分支。
◉ 问题与分支
我们在第 5 章中也提到了,修改源码时要先发起问题,然后根据问题编号创建相应分支。
○ 示例
为了修改源码,我们在问题跟踪系统中创建了编号为 #5 的问题(图 6.15)。
图 6.15 在问题跟踪系统中创建的问题
这种情况下,修改后的源码要提交到 t5 分支。于是我们新建 t5 分支。
$ cd ~ $ cd example-prj $ hg branch # 查看当前分支 default $ # 问题编号为5,所以从default 分支创建名为t5 的分支 $ hg branch t5
接下来,将源码添加成为管理对象,然后提交。
$ hg add $ hg commit
这样就可以将我们的修改提交上去了。
在这个状态下,default 分支并没有被修改,所以就算其中的代码传到其他版本库(比如发布版本库等),我们所作的修改也不会被发布(图 6.16)。
图 6.16 向分支提交之后的历史图
一般说来,修改过的源码不会很快被发布。
如果我们将暂不发布的源码提交到了 default 分支,那么一旦遇到需要插入临时发布的情况,就必需面临很多容易出问题的操作,比如多头现象、删除不合适的变更等。
只有到了发布那一刻才能将源码提交至 default 分支,也就是在开发过程中保证源码只出现在开发分支里,这样才能保证安全。
我们将工作版本库的更改传到主版本库,具体代码如下。
$ hg push --new-branch # 指定new-branch 远程添加分支
专栏 hg push --new-branch
不加任何选项的 hg push 命令不能在远程版本库创建新的头。不但已有的分支受此限制,而且在远程版本库新建分支的操作也包含在内。指定 --new-branch 选项可以在远程版本库添加新分支。另外,即便指定了 --new-branch 选项,我们依然无法给已有分支创建新的头,所以可以放心大胆地创建新分支并 push 变更。还有一点要注意,就算我们已经将本地创建的工作分支与 default 等合并,在 push 时仍然需要指定 --new-branch 选项。
6.6.5 提交设计
如何对待设计模板以及媒体文件是个非常难的点,而且根据设计师的技术以及工作人数的不同,这项工作的难度会有极大变化。一般说来,我们会使用 GUI 客户端通过 FTP、SCP 等将文件上传至服务器,确认其正常工作后再直接在服务器上提交文件。
◉ 在分支中进行设计
设计模板和媒体文件也要和源码一样提交到分支中。这是为了保证在与系统合并失败时能立刻还原到正常工作的状态。至于分支名,我们建议也和源码一样,起一个与问题编号相对应的名字。
如果设计需要频繁更改但系统没有变更,那么上面的方法会显得很繁琐,工作量很大。这种情况可以创建一个设计专用的分支,把所有和设计相关的变更都提交到这里(图 6.17)。
$ cd example-prj $ hg branch default $ hg branch design # 从default 创建设计专用的分支 $ hg commit # 提交
图 6.17 向设计专用分支提交后的历史图
◉ 伴随系统变更而产生的设计提交
在添加、修改系统源码之后,如果需要对设计进行添加或修正,那么设计师必须先将查看设计的分支切换至已提交系统源码变更的分支,然后再进行自己的提交。
6.6.6 分支的合并
◉ 发布时的合并
为发布(交付)在工作分支中开发的功能或设计,我们需要先将工作分支合并到 default 分支(图 6.18)。
$ hg update default $ hg branch default $ # 为发布t5 分支中的变更,要将该分支合并到default 分支 $ hg merge t5 $ hg commit
图 6.18 t5 分支合并到 default 分支后的历史图
◉ 用来追踪最新变更的合并
发布之后,未发布的分支也必须吸收这些变更,也就是要将 default 分支合并到对象分支(图 6.19)。把 default 分支的成果吸收到所有对象分支中能带来很多好处,比如对象分支向 default 分支合并时不会出现冲突。另外,对象分支的头与合并后的修订版,即 default 分支的新头之间不会有任何差别。这意味着只要合并前的分支通过了测试,合并后也必然能通过测试。
$ hg update t3 $ # 将default 分支合并到t3 分支,使t3 分支吸收最新的代码 $ hg merge default $ hg commit
图 6.19 default 分支合并到 t3 分支后的历史图
专栏 如何处理已经无用的分支
当我们完成某部分开发,将与问题相对应的分支合并到 default 之后,这个分支就没有用了。但是,它仍然会以(inactive)的形式残留在 Mercurial 的分支一览中。
$ hg branches default 7:a587bc0eb68e design 6:e3f875bb6623 t3 3:0440d428d18a t2 2:c4b2cd02f0c5 t1 1:c65aded0fe16 t5 4:9647e05b7580 (inactive) # 已经合并到default的分支仍会留在一览表里
inactive(非活动)状态表示该分支已经合并到其他分支(这里是 default)了。因此,有些尚未被发布的分支也可能进入 inactive 状态。如果不分清已经发布完毕的无用分支和仍要使用的分支,就很可能酿成遗漏发布等事故。Mercurial 有一个专门表示无用分支的状态closed(已关闭),我们可以将没有用的分支设置成这个状态。关闭某个分支(转入 closed 状态)时,需要先切换到该分支下,然后在提交时指定 --close-branch。
$ hg update t5 $ hg branch t5 $ hg commit --close-branch # 将t5分支转为closed状态 $ hg branches # 已被close的t5不再出现在一览表中 default 7:a587bc0eb68e design 6:e3f875bb6623 t3 3:0440d428d18a t2 2:c4b2cd02f0c5 t1 1:c65aded0fe16
closed 状态的分支虽然不会显示在 hg branches 命令的一览表中,但这并不代表分支被删除了。虽然不关闭分支不会对开发造成影响,但考虑到事故风险,还是建议各位将无用的分支关闭。
6.6.7 集成分支
在统合多个分支的变更内容时,我们要创建一个集成分支来合并它们。
◉ 创建问题
先创建问题来确定分支编号(图 6.20)。
图 6.20 集成分支的问题
◉ 创建集成分支
创建与问题编号相对应的集成分支 t6。
$ hg update default $ hg branch t6 $ hg commit # 提交分支
将要集成的对象分支合并到 t6(图 6.21)。
$ hg update t6 # 更新集成分支 $ hg merge t1 # 合并t1 分支 $ hg commit $ hg merge t3 # 合并t3 分支 $ hg commit
图 6.21 将对象分支合并到用于查看的分支后的历史图
发布集成分支中的全部内容时,要将集成分支 t6 合并到 default 分支。
$ hg update default $ hg merge t6 # 集成分支 $ hg commit
专栏 集成分支的用武之地
在变更内容出现冲突,或者需要在特定时间整合分支并统一发布等情况下,集成分支会显得非常好用。
另外,我们还可以将开发完成的各功能分支先合并到集成分支,经过综合测试之后再向 default 合并。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论