版本控制:入门与使用

从今天起,我们将陆续转载由中文 Haiku 社区的翻译者 Kurain 翻译的《Haiku编程教程》系列文章中对开源开发有所帮助的部分文档。虽然 Linux 和 Haiku 两个系统的差别很大,但他们同为开源项目,因而开发过程中有很多共通之处。如本篇指导,版本控制系统是开源社区最常用的工具之一,如果您正在学习相关的信息,相信这篇文章会让您有所收获的。

原文地址:Haiku编程教程 第四课

原网站:中文 Haiku 社区

源码控制:其为何物?

在我成为Haiku项目开发者早期的那段时间里,我遇到了很大的挑战,因为我必须使用源码控制管理器(SCM),我对它不了解,也不愿意花时间去看那些网上的指南。我只是希望能够尽可能写出好的代码。但是我真希望我那会儿就理解了源码控制。

源码控制,也称之为版本控制或者修改控制,它是一个或者一系列为保证不同的开发人员能够同时在单个代码库上进行开发提供的工具。它通过记录每个人所作出的修改,并保证一个人所做的修改不会和另一个人所做的同时进行记录。大多数工具也提供在独立源码库上(称之为分支,即branch)进行工作的特性。

SCM的使用将会强制您的工作流程具有一定的结构性,它们对于那些具有严格时间规划的人非常有益,并且这些人和非常喜欢这类工具。日复一日的编码涉及到检查其他人的更新,以及检查自己所做的修改。某些情况下,修改必须予以取消,即撤销(revert)修改。有时候某个特性改动很大,有必要进行多出修改记录(check-in),这称之为提交(commit)。在这种情况下,需要创建一个分支,这样将会有助于特性的添加,但并不会影响其他人的工作。在特性完成之后,将其合并到主源码树。

源码控制:为何使用?

在工作中使用版本控制带来的好处将会远远大于其所花费的时间。如果您是某个多人项目中的成员,修改跟踪的自动化管理将会为其他的任务节约很多的时间。同时它也免去了应用修改中的人为因素。虽然两三个人也可以通过邮件的形式协同工作,但是将会极大地增加引入错误的因素,并且还不易于延长时间。当然一两个命令就可以撤销修改的特性也会节约很多时间。

使用源码控制也会为企业带来一些不便。使用源码控制配置项目需要一定的时间。源码控制工具之间的迁移也比较困难。当然选择一个合适的源码管理工具并不容易 – 有许多可用的工具,并且它们的优势都不是很明显。配置您自己的SCM服务器,如闭源项目的商业或私有服务器,其本身也极具挑战。对很多”老鸟”来说,这些令人头痛的东西都是必备的,因为他们至少有一个项目实例,而源码控制工具让他们摆脱了其中的困境。

源码控制:使用哪个?

在其他平台上,如 Linux 或者 OSX ,有许多不同的源码管理工具可供使用。在本文编写时,Haiku就有四种可用的工具,如下所述。

并行版本系统(CVS)

CVS 是现存仍在使用的最古老的 SCM 之一。它最初是为了取代版本控制(Revision Control System;RCS)系列工具而开发的。其使用了客户-服务器架构,并且仍在广泛使用。一些人认为,和其他的选择相比,CVS 不值得使用,它的优势很少,并且带有很多其他工具不存在的限制因素,如无法重命名和移动文件。不建议初学者使用。

Subversion(SVN)

Subversion 是为了弥补 CVS 中的缺陷而发起的,并且也是得到广泛应用,非常受欢迎的源码控制工具。和 CVS 相似,Subversion使用了客户-服务器架构。它只是移动和重命名文件,分支创建相对快速,并且提交属于真正的原子操作。尽管如此,它也存在问题。一个颇受批评的地方就是,创建分支非常简单,但是将分支合并到主版本却不是很容易,并且非常乏味,还耗费时间。总之,它是一个非常好的工具,并且本书编写时,它是 Haiku 项目所选用的源码管理工具。

Git

Git原本是由Linux Torvalds 为 Linux 内核项目而开发。与 Subversion 和 CVS 所不同的是,它采用了一种不同的发布模式,即所有的开发者都拥有一个源码库的完整拷贝。它和 CVS 编写的目的相差甚远,其为了防止腐败,为了更加的快速,以及更像专有 SCM 软件 BitKeeper。Git带来了很大的开发热情。它主要的缺点是,在 Windows 下有两种实现方式,可惜两者都不理想。虽然它很快,很快,在适应它之前,你可能会遇到很多困惑。在许多方面,它的设计理念都和 Linux 操作系统非常相似。

Mercurial(hg)

Mercurial 是 Git 的同龄兄弟,它们几乎同时开始,并且基于同样的起因:BitKeeper 的供应商,BitMover,收回了原本对开源项目的自由使用授权,并且不在开发有竞争力的 SCM。它基本上由 Python 编写,并且在很多平台都可以使用,也包括 Haiku。和 Git 相似,它也具有一批追随者,并且在 Mercurial 用户和 Git 用户之间孰优孰劣的争论从未结束,这就像两种品味的可乐。Mercurial的设计理念和 OSX 与 Haiku 非常相近,简单但并不简化。对于源码控制的初学者而言,它是一个非常好的开始,并且之后我们也会再次涉及到它的使用。和喜欢的 IDE 相似,爱你所爱,用你所用。

源码控制第一步

尽管 Paladin 提供了源码控制的方便接口,它并没有深入的使用它所支持的工具。作为本节的目的之一,我们将会介绍命令行下 Mercurial 工具的基本使用。

按照约定,第一个任务是告诉 Mercurial,你是谁。在您的 home 目录下创建 .hgrc 文件,然后使用文本编辑器打开,在其中添加如下内容:

[ui]
username = My Name [email protected]

当然,您将会将其替换为自己的名字和邮箱地址。同时,除非你喜欢 Haiku 中包含的 nano编辑器,否则当您录入修改,描述修改时,您需要设置 Mercurial 所使用的文本编辑器。我所喜好的编辑器是 Pe,它是为 Haiku 特别编写的优秀文本编辑器。如果使用 Pe 作为文本编辑器,如果在 home 目录下不存在 .profile 文件,您需要创建它,然后在其中添加如下内容:

export EDITOR=lpe

如果您有自己偏好的其他编辑器,那么可以将其替换为相应的编辑器名称。如果该编辑器的可执行文件位于 /boot/system/bin,/boot/common/bin,/boot/home/config/bin 之外,您需要为其添加完整的路径。您的 .profile 文件是每个 Terminal 会话开始时都会执行的 Bash 脚本,因此您也可以在其中添加其他的自定义内容。

现在,初始化的设置都已经完成,我们需要创建一个源码库。Mercurial 可用于为新的或者已经存在的项目添加源码控制。打开 Terminal 窗口,进入空目录,输入如下命令:

$ hg init

它将会使用当前目录作为源码库的主目录。所有的子目录都是它的一部分,虽然空目录将会被忽略。您在输入该命令后,可能不会看到 Mercurial 打印任何信息,但是如果您输入 ls –a 命令,您将会看到已经创建的 .hg 目录,这个目录放置了 Mercurial 记录的整个源码库信息。现在我们已经可以开工了,在该目录下,创建一些文件,或者拷贝一些文件以备后续使用。

现在,我们要将您的测试文件添加到源码库。Mercurial 和其他的 SCM 将会只跟踪那些您让它们跟踪的文件,尽管它们当它们遇到无法识别的文件时会给予提醒。为Mercurial管理文件列表添加文件只需一个简单的命令:

$ hg add
adding ObjectArray.h
adding foo.cpp

当前目录下的所有文件和所有的子目录都将会添加到源码库。当然,您也可以在 add 后面指定文件或文件列表。添加文件到源码库并不会进行任何的改动,除非您录入(check-in)了这些修改。

在我们进行首次提交(commit)之前,通常需要保证您已经确切知道了所要做的改动。您有两种方法可以获知。第一种是使用 hg status。它将会打印那些还未更新的文件列表,需要添加的,删除的,修改的,以及未识别的文件。另一种方法是 hg diff,它显示了每个文件将要执行的实际修改。下面是 hg status 显示的内容:

$ hg status
A ObjectArray.h
A foo.cpp

自上次提交以来,需要添加两个文件;在这种情况下,则是从源码库创建以来。其他用于文件的指令如下表所示:

 

如果您对 Terminal 中经常使用 diff 命令还不熟悉,可以尝试一下 hg diff 命令,看看它是怎么工作的,但是需要准备一下,很多的文本内容将会打印出来。最好在 Terminal 中分页查看 diff 的结果,例如 hg diff | less,或者使用 Paladin 在一个滚动的文本窗口中查看。

在我们提交之前,我们需要检查一下,如果发生意外,我们不希望提交到源码库,那么我们该怎么做。假如,您为一个文件添加了一些用于调试的 printf() 函数,但是您不希望将它们添加到源码树。尽管,您可以仔细检查,并且手动将它们删除,如果这些 printf() 调用是唯一所做的修改,那么您可以撤销(revert)它们。

撤销文件将会撤销自上次提交以来对其所作的所有修改。如果您无意添加了一个不希望跟踪的文件,它将会被撤销添加。如果您无意删除了一个跟踪文件,那么 Mercurial 将会将其替换为新的拷贝。修改文件将会回溯为未修改状态。简而言之,它将会弥补任何你所犯下的错误,并且当您撤销一个修改文件时,Mercurial 将会创建一个 .orig 文件,其中包含了您所做的修改,以便某天您会需要它们。

撤销可以有多种方式。您可以撤销单个文件或者整个源码树。撤销也可以回溯至某个指定版本。它也可以在不备份所作改动的情况下执行。下面是 hg revert 的可用选项:

考虑到开发人员可能有无数种产生错误的可能,了解revert不同的工作方式将会节约您的时间,精力以及减轻压力。

接下来,让我们录入所作的修改。输入下面的命令开始提交:

$ hg commit

在输入这个命令之后,Mercurial 将会打开编辑器,让您添加描述该提交的消息。如果您没有在 .profile 中指定编辑器,那么它将会执行控制台文本编辑器 nano。使用”Initial check-in”消息或者类似内容,在编辑器中保存文本,然后关闭编辑器。Mercurial 可能(不)会打印一些东西。即使没有打印消息,下面需要确保您的首次提交是成功的。您可以使用 hg log 命令来进行确认,它可用于真个源码库或者单个文件。

$ hg log
changeset:	0:0dbb51f0e1fa
tag:		tip
user:		DarkWyrm [email protected]
date:		Sun Aug 15 21:30:56 2010 -0400
summary		Initial commit


使用Mercurial与其他人协同工作

如果您只是做自己的项目,并且无意与他们共同协作,这些命令也是您所需要用到的。然而,在开源托管网站,如 BitBucket 或者 Sourceforge 上构建项目也将会涉及到其他人的协同。

我们假定,您在 MyMercurial 站点托管了自己的项目 MyProject 。在提交程序之后,您获得了批准,并且该站点为您创建了源码库,那么接下来怎么办呢?

首先,您需要创建一份 MyMercurial 托管的源码库的本地拷贝。您需要从托管站点获取源码库的地址,并且该地址对于托管网站和您的项目都是唯一的。例如,源码库的地址(URL)为http://mymercurial.foo/hg/myproject。我们需要使用 hg clone 命令来创建本地源码库。Mercurial 将会打印一些类似的消息:

$ hg clone http://mymercurial.foo/hg/myproject
destination directory: myproject
requesting all changes
adding changesets
adding manifests
adding file changes
added 0 changesets with 0 changes to 0 files
updating to branch default
0 files updated, 0 files merged, 0 files removed, 0 files unresolved

现在您将会在当前目录下有一个 myproject 子目录。其中并没有任何文件,但是对我们来说,向远程代码库发送文件将非常容易。其余的工作就和我们之前所做的基本一样:拷贝项目文件到目录,使用 hg add 命令添加文件,使用 hg commit 命令录入修改。

在进行在线托管项目时,工作流程中会多一个步骤:推入(push)修改。和集中式源码控制工具如 CVS 和 Subversion 不同,提交(commit)仅应用到了您硬盘中的代码库。因此您需要使用 hg push 将您所作的修改导入到在线代码库。结果如下所示:

$ hg push
pushing to /boot/home/testrepo
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files

从在线代码库获取修改和将它们的导入非常相似。您可以通过命令 hg pull 来完成。它将会从在线代码库中获取修改,并下载它们。但是,它们并不会自动的将其合并到您的源码,除非指定 –u 切换。忽略切换意味着,在 pull 完成后,需要执行 hg merge 和 hg commit 命令。

解开伪装:源码控制就是个果壳

刚开始,使用源码控制可能有点复杂,但是SCM工具内容都不尽相同,并且多数情况下,基本内容并不会涉及很多东西。多数情况下,您需要遵循一定的工作流程:

  1. 编写或者修改代码
  2. 本地提交代码
  3. 重复步骤1和步骤2.,直到您准备更新在线源码库时,继续步骤4.
  4. 导入并合并远程修改。
  5. 将您的修改导出到远程代码库。

当您以这种方式进行看待工作流程时,它看起来也不很复杂,其实它也不复杂。更多高级的源码控制使用,例如使用分支,已经超出了本节的范围,但是并不会比上述的内容复杂很多。

如果源码控制这么简单, 为何大家都不使用它呢?在多数情况下,是因为对它的忽视,个人的懒惰,或者两者兼有。在开发工作中使用源码控制将会使您的工作更为容易,并且可以避免潜在的重大问题。

Now have One Response to “版本控制:入门与使用”

  1. gary.l 2012-02-07 19:54 says: 回复

    不错不错,学习资料保存一下。2002年我还在老机上安装了俳句前生的BEOS,因界面全是英文,玩了一下午就格掉了。

回复 gary.l