1. 简介
在软件工程的领域里,有一块叫做 SCM(Software Configuration Management),有人管它叫「软件建构管理」。SCM 的传统定义是原始码的版本管理,后来则逐渐演进扩大,还包含了软件开发的一些标准和程序的制定与应用 [Summerville 2000]。版本管理工具对目前的软件开发开环境来说相当重要,因为不管是软硬件环境的改变、需求改变、软件本身的 bug...等等,都会令软件不断地演进,我们必须记录各个版本,以便随时比对版本之间的差异,或者回到(rollback to)过去的某个版本;此外,当项目小组成员众多时,工作交接、多人修改同一个档案等情况,都有可能造成档案的版本混乱。例如一支程序本来由张三撰写,可是因为某些原因(请假、临时支持其它项目、请别人 debug....)暂时由李四修改,后来又交回给张三。如果用传统的档案共享机制,每次有这种情形就要互相通知:我改好啰,请把档案从档案服务器搬回你家,万一有人忘了,可能就会造成档案版本错乱,而东西交到客户手上才发现 bug 依然存在。
因此,如果你曾碰过下列情形,而且深感困扰,你可能就需要版本管理工具的协助:
目前市场上的版本管理工具已经有很多,环肥燕瘦任君挑选,以下几个可能是大家比较熟悉的:
CVS 虽然免费,也有窗口接口,但是入门门坎还是偏高,不易入手,以 unix/linux 社群用得较多;StarTeam 和 ClearCase 功能较强大,价格当然也较贵;PVCS 个人也没使用过,无法提供意见;而 Visual SourceSafe(VSS)功能虽然比较阳春,但是笔者试用之后,觉得如果只需要管理多人开发时的文件和原始码版本,其实还挺好用的,也很容易上手。VSS 在 Visual Studio .NET 光盘中就有附了,价格算是相当实惠。以下是使用 VSS 管理原始码的好处(有些不是 VSS 特有的):
注:撰写此文件时,使用的是 VSS 版本是 Visual Studio .NET 1.0 附的 Visual SourceSafe 6.0c。
1.1 基本概念
想象一下没有工具协助的情况下,当多人同时修改一份文件时,要如何确保文件的版本一致?
也许你可以指派一位专人负责管理文件的进出,这个人姑且就叫他 Manager 好了,Manager 待在一间小小的办公室里,负责文件库的维护和文件的进出。当小组成员 Eric 要修改文件时,就拿磁盘到这个窗口请 Manager 复制一份给他,Manager 在复制的同时会记下来:这份文件正由 Eric 修改;而 Eric 则会把磁盘拿到他自己的机器上,把档案复制到他的工作目录(working folder),然后进行修改。等到 Eric 修改完毕,再从工作目录中把档案复制到磁盘上交给 Manager,最后文件就被更新到文件库中(这动作叫做 check in),至此整个文件的修改与更新的程序就完成了。如果在 Eric 修改期间,Vivid 也拿着磁盘向 Manager 要求修改同一份文件,这时 Manager 会告诉 Vivid:这份文件目前已经由 Eric 领出(check out),且还在修改当中,你得等他改完才行喔。
以目前的作业环境来看,使用磁盘来传递档案似乎是原始人的行径,我们当然可以透过网络来传递档案,但是透过网络传递档案却无法提供上面的例子所要表达的重点:档案的锁定。而锁定机制就是 VSS(或其它版本管理工具)提供的基本功能之一,它确保了多人修改文件时,版本的一致性。上面这个例子当中的文件库,就相当于 VSS 的数据库,而 VSS 的客户端工具(称为 VSS Explorer)则扮演了 Manager 的角色。
当然 VSS 提供的功能更多,它也允许多人同时取出(check out)同一个档案进行修改,并且在将档案送回(check in)数据库时,自动进行合并(merge),这属于比较进阶的功能,稍后亦会提到。
现在你应该已经大概知道什么是 VSS 数据库、什么是 check in、check out,以及文件修改的流程了,接下来就把一些常见的 VSS 术语列出来,在阅读本文时,如果碰到不了解的术语,也可以随时回头查看。
以下是使用 VSS 时常见的术语:
术语 | 说明 |
VSS 数据库 | VSS 会使用一个数据库来储存各项目的程序 代码版本(包括历史版本和最新版本的档案)。 |
Projec | VSS 项目,是一个项目档案的逻辑结构,跟操作 系统的目录类似(注意不是指特殊开发工具的项目,例如:VB 专案)。 |
Working Folder | 客户端的项目工作目录。每次从 VSS 数据库取 出档案时,就会将档案复制客户端机器的这个目录下。 |
Master Copy | 储存在 VSS 数据库中的最新版的档案。 |
Local Copy | 储存在本机的 Working Folder 的版本。 |
Check Out | 把要修改的档案从 Master Copy 复制一份到本 机的 Working Folder 下,以便修改。 |
Check In | 本机的档案修改完后,把档案送回 VSS 数据库。 |
Get | 只从 VSS 数据库取得 Master Copy 的档案,但 是不做修改。当你要取得档案的最新版,并且只对它读取时,可使用此功能。 |
Multiple Checkouts | 一个档案同时被多人取出修改。 |
Merge | 合并 Multiple Checkouts 的修改结果。 |
Shadow Folder | 影子目录,它是一个硬盘上的实体目录,每当开 发人员 check in 档案时,VSS 就会同时将档案复制一份到这个影子目录里面。 |
2. 安装与使用范例
本节分别介绍 server 端与 client 的安装及使用。
2.1 服务器端
服务器端包含了管理工具和客户端工具的安装,相关的管理及设定工作有下列几项:
以下是各项工作的施行细节,我们会在 D:/VSS_DB 目录下建立一个新的 VSS 数据库,如果你不想要建立数据库,也可以使用预设的数据库。
2.1.1安装 VSS
直接执行安装程序,安装过程中会有一个安装选项画面,其中有三个选项,分别为 SHARED DATABASE SERVER、CUSTOM、与 STAND-ALONE。请选择 SHARED DATABASE SERVER。
安装完成后,在〔开始/程序集〕里面会有一个 Microsoft Visual SourceSafe 数据夹,里面有四个程序快捷方式:
2.1.2建立数据库
开启 Visual SourceSafe 6.0 Admin,如果是第一次执行,程序会提示你要设定 Admin 账号的密码,若此时不设定,以后也可以在〔Users/Change Password〕里面变更 Admin 账号的密码。
进入 VSS Admin 之后,先点选〔Tools/Create Database〕建立一个自己的数据库,建立数据库时会同时建立一个预设的管理员账户 'Admin',此账户无法删除。
一个数据库里面可以包含多个项目,当然你可以视需要建立多个数据库,只是一次只能使用一个数据库。
假设你将数据库建立在 D:/VSS_DB 目录。
2.1.3建立使用者账户
数据库建立好之后,必须先开启数据库,然后就可以为这个数据库建立 user 账号,以便日后为各个 user 赋予适当的档案存取权限。这些 user 就是开发小组的成员。
欲开启数据库,请点选〔 Users/Open SourceSafe Database〕或者按 Ctrl+O,然后选择上一个步骤建立的数据库,如下图:
如果之前建立的数据库没有显示在清单里面,请按右边的 Browse 钮找到该目录(此动作只需一次),然后按 Open 钮,即可开启数据库。
数据库开启后,点选〔Users/Add User〕或按 Ctrl+A 即可新增一名使用者。
2.1.4设定其它选项
在 VSS Admin 中点选〔Tools/Options〕即可开启选项设定窗口,其中有些设定在客户端(VSS Explorer)里面也有,而这里的设定是全域的,也就是如果客户端没有修改自己的设定,就会取用这里的设定。
建议的设定值(True/False 表示勾选/不勾选):
页夹 | 项目名称 | 设定值 |
General | Use network name for automatic user log in | True |
Project Rights | Enable Rights and Assignments commands | True |
2.1.5设定共享目录
你至少要把 server 端的两个目录分享出来给其它网络使用者存取:
1. 分享 VSS 的应用程序目录,以便客户端可以在网络上直接执行其中的 NetSetup.exe 进行安装。
2. 分享数据库所在的目录,如前面范例中的 D:/VSS_DB。
注意:
如果你在分享 VSS 的应用程序目录时,把目录权限设为「只读」的话,客户端安装完后将无法自动执行 VSS(但仍可手动执行);若目录权限为「完全控制」则不会有这个现象。
2.2 客户端
2.2.1安装客户端
安装客户端程序的方法有两种:
1. 向管理员询问服务器端的 VSS 应用程序分享目录,然后直接执行该目录下的 NetSetup.exe`.
2. 利用光盘安装,安装型态选择 "Custom",然后选择 "Client Programs"。
2.2.2开启数据库
安装完成后,执行 VSS Explorer(在「程序集」中的名称是 "Microsoft Visual SourceSafe 6.0"),第一次执行时会出现登入窗口,输入要登入的数据库名称(浏览网络上的芳邻,找到 2.1.5 节所分享出来的数据库目录),然后输入使用者名称和密码,即可登入数据库。参考下图:
VSS Admin 提供一个选项,可以在登入时自动以目前登入 Widnows 的使用者名称来登入数据库,前提是 VSS 的使用者名称要和 Windows 的使者名称相同。方法是将 VSS Admin 的〔Tools/Options〕的 "General" 页夹中的 "Use network name for automatic user login" 项目打勾。以后再次执行 VSS Explorer 时,就会自动以该使用者名称登入,而不会出现登入画面。
2.2.3建立项目
登入数据库之后,由于是第一次执行,所以没有建立任何项目,看到的画面会像下面这张图:
左边是以树状显示的项目面板,"$/" 是 VSS 的 root project,所有的项目都是建立在此节点之下;右边会显示目前的项目的档案清单;下方状态列中则显示提示讯息、目前登入的使用者名称、档案的排序方式、以及档案数量。
以下步骤示范如何建立一个项目,该项目的档案目录已经事先建立好,位置是 "D:/Projects/Demo1/",而且该目录下已经存在所有文件和程序代码档案。
1. 在项目面板中的 $/ 节点上面点一下右键,然后点选〔Create Project...〕。在接下来开启的窗口中输入项目名称 "Demo1",再按 Ok 钮即可建立项目。
2. 接着将档案加入此项目节点。做法是在项目面板中的 "Demo1" 节点点一下,然后点选〔File/Add Files...〕或按 Ctrl+A。
3. 接着将项目 Demo1 目录下,要加入版本管理的子目录加进来,例如:若要加入 Src 目录,则照下图方式操作:
注意必须双击欲加入的数据夹,使其图标变成开启的样子,才是加入该数据夹。确定之后按 "Add" 钮即可加入,加入数据夹的窗口左下角的 "Recursive" 项目通常会打勾,也就是该数据夹底下的子目录也要一并加入。
Tip: 你也可以用鼠标拖曳的方式加入档案或资料夹。
Tip: 当你在加入档案时,如果临时要取消,可以按画面方状态列最左边的〔Cancel〕钮。事实上,只要是比较花时间的工作,都会出现〔Cancel〕钮让你有机会取消工作。
4. 数据夹加入之后,程序会询问你是否要将此数据夹设定为工作目录(working folder),回答 "Yes" 即可。参考下列画面:
此对话盒关闭后即会回加入数据夹的窗口,若不需要加入其它目录,就按 "Close" 钮关闭此窗口。
5. 此时画面应会显示如下图:
注意项目面板中的节点必须设定成工作目录(working folder)才能够对该目录执行 check in/check out 动作,例如此范例中的 Demo1 节点,它是我们自行建立的逻辑项目,并未设定其工作目录(也就是没有对应到实体的目录),因此当你点选 Demo1 节点时,右边面板上方的状态会显示 "No Working Folder"。
如果你需要将 Demo1 目录底下的所有目录都纳入 VSS 管理,也可以省略步骤 1,而在步骤 2 加入档案时,直接开启 "D:/Projects/Demo1" 数据夹,这样就会连同 Demo1 这个目录一并加入,且同时为它设定工作目录。
2.2.4设定工作目录
建立项目之后,接着就是要设定工作目录。首先,在 VSS Explorer 的项目面板里面找到你的项目,在该项目上点一下鼠标右键,再点选〔Set Working Folder...〕,把目录指向你的本机硬盘的项目目录即可。只要父层的节点有设定工作目录,其下的子节点就不用再指定工作目录了。
设定好工作目录之后,就可以利用 VSS 执行 Check Out 或 Get 动作。如果你希望把整个项目的目录和档案都先从从服务器取回来,并且复制到你的工作目录下,你可以使用 Get;方法是在项目名称上点一下鼠标右键,再点选〔Get Latest Version...〕,此时会开启一个对话窗口,如下图所示:
注意左下角的 "Recursive" 项目,通常我们会希望连子目录一并取回,所以要将此项目打勾。确定之后按〔OK〕钮即可,遇到不存在的目录,VSS 会问你要不要建立,选 "Yes All" 即可,完成之后,你可以开启档案总管,看一下工作目录中的文件目录结构,如果执行的步骤正确,你需要的项目档案和目录 VSS 应该都已经帮你从服务器复制过来了。此动作并非必要,你可以等到你要读取或修改某个档案时,再去 Get 或 Check Out 该档案,到时候 VSS 一样会帮你建立必要的目录。
如果你希望每次取得(get)或 check out 档案时,"Recursive" 项目都要自动勾选,你可以在〔Tools/Options〕的 "General" 页夹更改这个预设设定,参考下图:
项目完成时,或者需要对现有版本进行建置与发行时,可以在服务器的计算机上开启 VSS Explorer,利用〔Get Lastest Version〕取得最新版本,你便可以在服务器端进行建置或者备份项目的工作;或者,你也可以透过影子目录(shadow folder)的功能,来达到相同的目的(参考 3.4 节)。
3. 其它功能
本节将介绍 VSS 的其它功能,包括:
3.1 多重 checkouts
VSS 预设不允许多重 checkouts,也就是当一个档案或目录被一个使用者 check out 之后,其它使用者就不能再 check out 该档案目录。当你的小组可能为多人同时修改一个档案,或多人同时修改一个目录里面的各个档案时,可以将多重 checkouts 的功能开启。设定方法是在 VSS Admin 管理工具里面,将〔Tools/Options〕的 "General" 页夹里的 "Allow multiple checkouts" 项目打勾。
使用多重 checkouts 时,有些值得特别注意的地方,例如:一个档案由多人同修改时,VSS 将如何处理?以下将说明相关的注意事项。
文字文件 v.s. 进位档
当你开启多重 checkouts 选项时,表示有可能一个档案同时由多人修改,而 VSS 能够将这些人对同一个档案的修改结果合并(merge)起来,每当一个使用者 check in 档案时,VSS 就会自动进行 merge。也由于 VSS 提供了这项功能,因此限定只有文字文件(text files)才能够多重 checkouts,二进制档案(binary files)仍然是禁止的。VSS 会自动判断档案是属于文字文件还是二进制文件(藉由搜寻二进制的 /0x0 字符),你也可以预先指定好哪些档案类型是二进制文件,省得 VSS 还要花时间判断;方法是:开启 VSS Admin 的〔Tools/Options〕,切到 "File Types" 页夹,把二进制档案的附文件名加入 "Binary files" 字段里。参考下图:
注:所谓的文字文件,通常是指可以用记事本开启的纯文本文件,因此 WORD 文件(.DOC)档案应该归类为二进制档案。
图中的 File groups 清单里面,笔者自行加入了 Delphi 项目会用到的档案类型,这项设定是用在当你加入档案时,显示在档案类型下拉盒中,方便你挑选档案而已,如下图:
其实大部分的情况下,用预设的 "*.*" 就行了。
合并机制
当一个档案被多人 check out 时,每当有人将该档案 check in,VSS 就会自动比对档案的差异,并且合并有差异的部分。考虑下面的场景:
1. 张三与李四都 check out 了 foo.txt 这个档案。
2. 张三修改了 foo.txt 的第 100 行,并且 check in。
3. 李四修改了 foo.txt 的第 200 行,并且在 210 行的地方加入了 5 行程序代码。
4. 李四改完了,并且 check in。
上面的例子对 VSS 来说毫无困难,它会安静地自动合并张三和李四所做的修改。但不是所有情况都这么完美,万一两个人都修改了同一行程序代码,此时 VSS 就无法替你做决定,必须由你自己决定怎样合并档案。考虑下面的场景:
1. Carol 与 Michael 都把 test.txt 取出来修改。
2. Carol 修改了第 1 行,然后 check in。
3. Michael 也修改了第 1 行,然后 check in。
这时候 VSS 无法判定到底要怎么合并,于是开启窗口显示两个版本的差异,让后面 check in 的人(Michael)决定怎么合并,参考下图:
图中分为三个面板,左上角的面板是目前服务器上的版本(上一个人 check out 的版本),右上角是本地端的版本,下方面板则是合并后的版本;此时 Michael 就可以从两个版本中观察差异的部分,决定好怎么修改后,在左边或右边面板中点鼠标右键,选择〔Apply Change〕来把要改变的内容套用到下方面板。你也可以修改下方面板的文字内容,改好后按工具列的储存钮(磁盘的图标)即可。
附带一提,你可以从 VSS Explorer 显示的画面看出一个档案是否被多人取出修改。如下图的 test.txt,在文件名称的左边有两个勾勾的图示,而 User 栏则显示最后一次 check out 的使用者名称,后面加上 "..."。
值得采用吗?
万一 VSS 无法自动合并,手动合并似乎有点麻烦,这样做值得吗?还是干脆不允许多重 checkouts?
笔者的建议是,只有当你真正碰到的时候,才把这个功能打开。举例来说,在一个项目里面,可能会有一些共享的程序代码,这些共享的程序代码平时可能由一个人维护,例如:AppUtils.cpp;但是也有可能别的程序设计师写了一些共享的函式,为了避免共享的程序代码散乱在太多档案里面,于是他希望把自己写的共享函式也放到 AppUtils.cpp 里面,于是便形成了多人要维护同一个档案的情形,此时就很适合使用多重 checkouts 了,因为虽然改的是同一个档案,各人要改的部分会彼此冲突的情况不多,此时 VSS 将可以自动处理 90% 以上的合并。
3.2 档案的共享(Share)与分枝(Branch)
你可以指定一个档案让多个项目共享,方法是在 VSS Explorer 的项目面板中,挑选要共享的目录,注意不是分享出去的目录,而是指你现在想要使用别人的共享档案的那个项目目录,在该目录上点右键,再点选〔Share〕,这时候出现的窗口才是要挑选来源的共享档案,在窗口中选好要共享的档案,然后按〔Share〕即可。参考下图:
档案4.设定成共享之后,当你对共享档案 check out,不管是提供共享档案的来源项目,还是使用这些共享档案的项目,其目录下都会有一份共享档案的拷贝,但是 VSS 保证这些档案内容都会一致,VSS 透过 Share 的设定来维护各项目间共享档案的连结,让共享档案维持一个版本。
你也可以透过分枝(Branch)的功能来切断共享档案的连结,这意味着你不要再跟别人共享这个档案了,而希望保有独立发展的版本。做法是在 VSS Explorer 的右边面板中,点选要切断共享关系的档案,然后点选〔SourceSafe/Branch...〕,接着会出现窗口请你确认,按〔OK〕钮即可。切断共享关系之后,其它项目的共享关系依然存在,只有自己跟别人脱离关系而已。
3.3 影子目录(Shadow Folder)
由于所有的修改记录和最新版本的档案都存在 VSS 数据库中,如果其它人(例如:项目经理、系统分析师、建构师)经常需要读取最新版的档案,但是又不想要安装 VSS,就可以使用 Shadow Folder 功能,让这些人可以透过档案总管的方式读取档案(只能读取,不能修改)。设定 Shadow Folder 的方法是在 VSS Admin 工具中点选〔Tools/Options〕,然后切到 "Shadow Folders" 页夹,先输入要设定 shadow folder 的项目,你也可以点旁边的〔Browse〕钮,用鼠标来选择项目;接着输入影子目录的实体路径名称,设定完之后按〔确定〕钮即可。如果你要一次设定多个项目的影子目录,可以在每一个项目设定完后按〔Set Another〕钮。参考下图:
如果要取消影子目录,只要先输入项目名称,然后把 "Set shadow folder to" 这个字段清除就行了。
注意:
4. 结语
最后,笔者整理出几个使用 VSS 时的重点步骤及快速键(假设数据库和使用者账户都已经建立好了):
其中只有最后两个步骤是开发人员经常执行的动作。
VSS 主要是依靠将档案属性设定成只读来提供档案锁定的机制,而其档案传递的途径则是透过传统的 NetBIOS 和档案共享机制,这使得 VSS 的应用范围只能限制在局域网络内,如果能透过 TCP/IP 的方式传输档案,适用的范围会更广,也会更方便 [注1]。
透过本文的介绍,笔者希望能让你对 VSS 有一个初步的了解,并且能很快地学习如何使用它,当你真正开始使用它,就会逐渐发现一些新的或者一些比较细节的东西,此时再到网络上寻找解答,这样可能会比读完很多份文件以后才开始安装使用要来得快一些。如果你要更深入了解 VSS,可以参考文后列出来的参考资料,微软网站上亦提供了相当丰富的文件,从这个网址进入: http://msdn.microsoft.com/ssafe/ ,里面有 VSS 的最新消息和大量的技术文章、教学文件,你可以从这些文件里获得对 VSS 更完整的认识,并且学习一些进阶的管理议题,例如:VSS 数据库的保全、分析、修复、与备份;VSS 的自动化(automation);与其它 IDE 工具的整合等等。在学习使用的过程中如果碰到问题,可以利用网络论坛来寻求解答,这里列出几个供读者参考: