传统的版本控制辅助档案的备份,追踪与同步. 分布式的版本控制让变更的分享简单容易.
如果你做的对, 你可以鱼与熊掌兼得: 简单的合并同时并可以集中版本发布.
要分布式的吗? 一般的版本控制到底发生什么问题?
没有问题 — 如果你想快速回忆的话请参考VCS版本控制视觉指引 . 当然,
有些人可能会嘲笑你还在用”古老”的系统. 但在我看来仍然是OK的: 对于任何项目来说有用版本控制系统总是正向的一步.
集中的版本控制系统在1970年代出现, 当初程式设计者有了精简型终端机(thin clients)但同时也欣羨又大又贵又快速的”big
iron” mainframes(谁能不被当时风行的大小通吃8bits到1 byte的机器吸引呢?)
集中管理是简单的概念, 很自然是第一步想到的:让每个人到同一个地方签入签出,
就像集中到某个图书馆的书本上注记一样.
如此的做法对于备份,复原和同步行得通, 不过对变更的合并与分支却不太行.
当项目成长时, 通常会想将功能切割, 独立开发与测试, 再逐步将变更并入主开发线. 实际做时, 分支就很麻烦,
新的功能可能要做庞大的签入, 如果中间有任何差错, 变更变得很难管理也很难做问题排解. 当然, 集中控管的系统也总有”可能”做合并,
但并不容易: 你需要亲自确实追踪合并的动作与内容, 以避免同样的变更被做两次. 分布式的版本控制系统让分支与合并无痛执行,
因为这是此类系统的长处. (译注: SVN支持Merge Tracking后就可以避免同样的变更会合并两次以上的问题)
请看一些图解
别的教学多是严肃的命令列指令, 在此提供您视觉化的说明. 让你回想一下运用典型集中控管的版本库的状况:
每个人与主开发线同步也将档案签入主开发线: Sue加入soup, Joe加入juice,
Eve加入eggs. Sue的变更必须先签入主开发线才会被其他人看到. 的确, 理论上, Sue可以另开一个新的分支让其他人测试她的变更,
可是在一般的版本控制系统(VCS)如此做很麻烦.
分布式版本控制系统(DVCS)
依分布式模式, 每位开发者有他们自己的版本库. Sue的变动存在她个人端计算机的版本库,她可以决定是否要跟Joe或Eve分享:
不过是否有可能造成像无头的圆环一样循环呢? 不会的, 如果想要的话,
每个人可以将他的变动推(push)给同一个版本库, 存疑地, 就像上述集中的模式一般. 此人为的版本库(franken-repo)包含了Sue,
Joe和Eve的变动.
我希望分布式版本控制DVC(distributed version control)可以有不同的名称,
如 “独立的(independent)”, “联合的(federated)” 或 “点对点的(peer-to-peer)”.
此字 “分散”让人联想到分布式运算, 工作被分派给一群机器(如寻找外星智慧讯号的 SETI@home {可参考SETI@home台湾网站}
或做 蛋白质摺叠分析Protein folding).
而DVCS并不像Seti@home: 每一端(node)是各自独立的且是否分享由各端自我决定(在Seti,
你必须回覆你的结果)
5分钟说明主要观念
此给你基本概念; 如果你有兴趣, 可参考相关patch theory的说明书
.
核心概念
- 集中式版本控制聚焦于同步,追溯(tracking), 和备份档案.
- 分布式版本控制聚焦于变动分享; 每一变更有其 全域唯一辨识码(guid-global unique
id)或unique id.
- 记录/下载以及采用一个变更被视为分别的步骤 (在集中式系统, 此三者同时发生).
- 分布式系统没有强制的架构. 你可以建立”中央管理”区或让个人保持各自端运作.
新术语
- 推(push): 将变更送给其他的版本库 (应该需要其它版本库拥有者的允许)
- 拉(pull): 从另一版本库下载同步档案变更
关键优势
- 每人都有其本地端的沙盒(local sandbox). 你可以在自己的工作计算机上修改或回覆前版,
不需要大量的签入. 你自己的工作记录都累积存在自己的版本库.
- 可离线工作. 你只有当你想分享变更时才需要上线. 否则你可随你高兴一直在自己的工作计算机上独立作业,
签入或复原, 没有所谓”伺服器”当掉或在飞机上的问题.
- 速度很快. 差异(diff), 提交源码与变更回复都在本地端即可完成. 没有因网路或伺服器不稳而必须用一年前开发版本的问题.
- 可妥善做变动的处理. DVCS针对分享的变更做建置. 每个变更都有其独一无二的辨识码(GUID)以方便追踪.
- 分支与合并很容易. 因为每一开发人员”有自己的分支”, 每一分享的变动就像交换整合. 但独一无二的辨识码(GUID)让自动合并变更与避免重复合并动作变的简单容易.
- 较少的管理. DVCS很容易执行; 没有所谓的“总在运作的”伺服器软体需要安装. 此外, DVCS也不太需要你去”加”新的使用者;
你只是去捡选你想从那里拉(pull)版本库的URLs. 这样可以避免大型项目中令人头痛的政治性问题.
关键劣势
- 仍需要备份. 有个说法是你的“备份”就是其他人有你变更资料的终端机信息. 我无法认同—如果这些其他人终端机资料并没有采用你所有的变更呢?
或是当你变更的时候他们都不在线上? 用DVCS, 你仍希望可以有台机器让你push所有的变更到那里保存“以防万一”.
(在Subversion, 你有一台随时待命的机器做主要的资料贮存库, 建议您在DVCS也做一样的事).
(译注: 如有兴趣了解架设与管理DVCS服务器的工具, 欢迎参考CodeBeamer+Mercurial实务操作手册
与 CodeBeamer+Git实务操作手册)
- 没有所谓的“最近的版本”存在. 如果没有集中地, 你无法马上知道是否要到Sue, Joe或Eve那取得最近变更的版本(version).
再者, 一个中央集中地才可帮助大家清晰知道最近的”稳定版本”为何.
- 没有真正的修订版号码(revision numbers). 每一版本库有依变更做出的修订版号码.
和传统的版本库不同的方法,人们依变更的修订号码做沟通: “请问你有变更号码 fa33e7b? ” (记住,
这ID是一个不好看的GUID总体唯一辨识码). 还好, 你可以用有意义的名字贴标你发布的版本.
Mercurial 快速上手(Quickstart)
Mercurial速度很快,是个简易的DVCS. 暱称是hg, 就像水银(Mercury)元素一样.
一旦Mercurial已经初始化一个目录, 看起来将如下:
你将有:
- 一个工作拷贝(working copy). 你正在编辑的档案群.
- 一个版本库. 一个目录(Mercurial的.hg)包含所有的补钉(patches)以及可转译资料(metadat:comments,
guids, dates, etc.). 因为没有集中的伺服器, 所以这些资料都放在你这里.
在我们的分布式案例, Sue, Joe和Eve有他们各自的版本库, 储存他们不相干的修订版历史资料(revision
histories).
理解更新(Updates)与合并(Merging)
在研究DVCS时有几项让我有些混淆.
第一, 有几步将造成更新(updates)
- 取得变更到版本库:推(pushing) 或 拉(pulling)
- 采用变更到档案中:更新(update) 或 合并(merging)
- 储存新版:签入/提交源码(commit)
第二, 依据变更, 你可以更新或合并:
- 当无模糊地带时,更新(Updates)发生. 譬如, 我将变更拉(pull)到一直以来都是你在编辑的档案.
因没有重叠的变更,档案将跳到最近的修订版(revision).
- 当我们的变更发生冲突时,就有必要合并(Merge). 如果我们两个都去编辑档案,最后会变成两个”分支”,
类似平行宇宙(alternate universes-多种假设同时发展的各个故事)的样子. 有个我修改的世界,
也有个你修改的世界. 在此例, 我们可能想要合并成一个单一的宇宙.
我仍在整理DVCS到底可多容易的产生分支与摺叠分支:
在此案,因为 (+Soup) 和 (+Juice) 为同一个母项(parent-仅一个
“Milk”的列表)的变更, 有必要做合并(merge). 经过Joe合并档案后, Sue可以做一般的
“pull和update” 即可获得Joe已合并的结果. 她不需要亲自做合并的动作. .
在Mercuril, 你可如下执行:
是的, “pull-merge-commit” 周期蛮长的. 幸运地,
Mercurial有整合多指令(commands)为单一的捷径. 虽说看起来好像蛮复杂的, 但仍比在Subversion手动合并简单多了.
大多数的合并是自动完成的. 当发生冲突时, 一般可以很快被解决. Mercurial持续追踪每一变更的母/子关系(我们的合并列表有两个母项),
与”最新版(heads)”或每一分支的最近变动. 在合并前我们有两个heads;之后, 一个.
组织一分布式项目
此为一种组织方式:
Sue, Joe和Eve将变更加入一共同的分支. 他们可以跟任一人交易补丁(patches)来做”兄弟建置(buddy
builds)”:嘿 老兄, 请问要试试这些补丁吗? 在推给实验分支(experimental branch)前,我需要看看此是否可行.
然后, 经维护守门员在看过,将实验分支的变更拉到稳定的分支(stable
branch), 此有最近的版本. 分布式的版本控制系统(DCVS)帮助每一变更独立进行, 但也提供集中系统所有的”单一来源(single
source)”. 有多种开发的模式可用, 如”pull only”,此只有维护守门员决定是否要从别人拿取变更资料,
Linux的开发采用此种,或”shared push”, 此和集中管理的系统作业模式很类似. DVCS让您弹性选择要采用哪种方法来维护您的项目.
|