使用 Arch 进行版本控制:Arch 简介

作者:Nick Moffitt

Arch 正在迅速成为自由软件开发者工具集中最强大的工具之一。这是三篇系列文章中的第一篇,该系列文章教授 Arch 的基本用法,用于分布式开发,管理共享存档以及围绕 Arch 项目编写自动化系统脚本。

本文向您展示如何从公共 Arch 存档中获取代码,向上游贡献变更集以及为断开连接的使用创建项目的本地分支。此外,它还提供了提高本地和远程存档性能的技术。

版本控制的历史

版本控制是项目中变更管理的业务。检查项目所做工作、比较开发路径以及复制和撤消变更的能力是自由软件开发的基础部分。由于有如此多的潜在贡献者和如此快速的变更发布,开发者用来操作这些变更的工具不得不快速发展。

早期的版本控制是通过磁带备份来处理的。项目的旧版本将从备份存档中拖出,并与新副本逐行比较。从磁带恢复备份的过程并不快,因此这绝不是一种有效的方法。

为了解决这种滞后问题,许多开发者保留旧的文件副本以进行比较,这很快就被集成到早期的开发工具中。基于文件的版本控制,例如 Emacs 编辑器使用的版本控制,使用编号的备份文件,因此您可以比较 foo.c~7~ 和 foo.c~8~ 以查看发生了哪些更改。版本化的备份文件甚至被集成到某些早期专有操作系统的文件系统中。

近二十年来,向自由软件项目贡献第三方代码的首选格式一直是补丁文件,有时也称为 diff。给定两个文件,diff 程序会生成一个列表,突出显示它们之间的差异。要应用 diff 输出中指定的更改,用户只需通过 patch 程序运行它即可。

在 20 世纪 90 年代,并发版本系统 (CVS) 成为管理核心开发者团队变更的默认系统。CVS 存储补丁列表以及署名信息和变更日志。一个原始的分支和合并系统允许用户尝试各种开发路线,然后将成功的成果折叠回主项目。

CVS 有其局限性,并且正在成为许多项目的负担。首先,它不存储任何元数据更改,例如文件的权限或文件的重命名。此外,提交不会分组在一起,因此很难检查跨越多个文件和目录的更改。最后,几乎所有对远程 CVS 仓库的操作都需要打开与服务器的新连接,这使得断开连接的使用变得困难。

诸如 Subversion 项目之类的努力在很大程度上弥补了 CVS 中发现的缺陷。Subversion 实际上是 CVS++,它支持文件元数据更改日志记录和原子提交。它仍然需要的是网络上的中央服务器,所有客户端都连接到该服务器以进行版本管理操作。

分布式版本控制系统

在过去的几年中,新一代版本控制系统涌现出来,所有系统都在分布式模型上运行。分布式版本控制系统摒弃了单一的中央仓库,转而采用对等架构。每个开发者都维护一个仓库,这些工具允许轻松地在系统之间通过网络操作变更。

诸如 Monotone、DARCS 和 Arch 之类的项目在自由软件开发发生在连接良好的大学之外且笔记本电脑更为普及的世界中越来越受欢迎。

当今最有前途的分布式系统之一是 GNU Arch。Arch 通过鼓励用户在其本地机器上创建存档来处理断开连接的使用,并提供强大的工具来在存档之间操作项目。Arch 缺少任何类型的专用服务器进程,并使用文件系统操作的可移植子集来操作存档。存档只是目录,可以使用您首选的远程文件系统协议通过网络提供。此外,Arch 支持通过 HTTP、FTP 和 SFTP 访问存档。

没有专用守护进程的一个优点是,没有新代码被授予您服务器机器上的特权。因此,您的安全考虑因素是您的 SSH 守护进程或 Web 服务器,大多数系统管理员已经在关注它们。

另一个优点是,对于大多数任务,无需 root 权限即可使用 Arch。开发者可以在他们自己的机器上开始使用它并发布存档,甚至无需在 Web 服务器机器上安装 Arch。这也影响了采用模式。使用 CVS 或 Subversion 是为整个项目团队做出的自上而下的决定,而 Arch 可以一次被一两个开发者采用,直到团队中的每个人都赶上进度。

获取 tla

Arch 最初是一组 shell 脚本和围绕 Tom Lord 的 hackerlabs 库的包装器。当时的程序名称是 larch,使用起来有点笨拙。客户端现在已完全用 C 重写,名为 tla,代表 Tom Lord's Arch。界面仍然不完美,但对于熟练的开发者来说,日常使用已经足够好了。大多数 GNU/Linux 发行版都提供了 tla 软件包(请参阅在线资源)。

检出只读项目

一旦您安装了 tla,最好通过检出一些代码来测试它。Arch 将您的数据存储在一个称为存档的目录中。在存档中,数据被组织成嵌套的类别:项目(作为一个整体的工作名称)、分支(特定的开发线程或其他描述性术语)和版本(一个简单的数字指示器,您可以用来指示特定分支的进展程度)。

获取代码的第一步是注册一个公共存档,以便 Arch 将名称与存档位置关联起来

$ tla register-archive http://www.lnx-bbc.org/arch

现在您应该在运行以下命令时看到列出的 lnx-bbc-devel@zork.net--gar 存档tla archives。如果您对其中存储的项目感到好奇,可以使用tla abrowse命令获取完整列表

$ tla abrowse lnx-bbc-devel@zork.net--gar
lnx-bbc-devel@zork.net--gar
  lnx-bbc
    lnx-bbc--research
      lnx-bbc--research--0.0
        base-0 .. patch-10

    lnx-bbc--stable
      lnx-bbc--stable--2.1
        base-0 .. patch-29

  scripts
    scripts--gargoyle-bin
      scripts--gargoyle-bin--1.0
        base-0 .. patch-7

此列表告诉我们 lnx-bbc-devel@zork.net--gar 存档有两个项目,lnx-bbc 和 scripts。lnx-bbc 项目有两个分支,research 和 stable。lnx-bbc--research 分支只有一个版本 (0.0),该版本在存档中记录了十个更改。lnx-bbc--stable 分支只有一个版本 (2.1),包含 29 个变更集。

因为您现在已将 LNX-BBC 公共存档注册到您的本地列表中,所以您可以检出 LNX-BBC stable 分支的副本

$ tla get \
lnx-bbc-devel@zork.net--gar/lnx-bbc--stable lnxbbc

一旦它完成下载并应用补丁集,您应该会有一个名为 lnxbbc/ 的目录,其中充满了文件。为了模拟代码中的更改,cd进入 lnxbbc/ 并编辑 robots.txt 以在某处添加新注释。

贡献变更

现在您已经进行了更改,运行tla what-changed应该打印M robots.txt以指示 robots.txt 已被修改。要获取更改的详细信息,您可以运行tla what-changed --diffs,它应该打印出一个 diff 文件,可以发送回项目开发组

--- orig/robots.txt
+++ mod/robots.txt
@@ -1,3 +1,5 @@
+# Welcome, robots!
+
 User-agent: *
 Disallow: /garchive/
 Disallow: /cgi-bin/

这样做的缺点是 diff 不指示元数据更改。移动的文件不会被列出,并且当另一个开发者通过 patch 运行此 diff 时,新文件不会被创建。为了向项目维护者提交更复杂的更改,您必须生成一个变更集。

在 Arch 中,变更集表示为一个目录树,其中充满了簿记文件、补丁、新文件和已删除文件。最佳贡献技术是创建一个变更集目录,然后将其打包以进行交付

$ tla changes -o ,,new-robot-comment
$ tar czvf my-changes.tar.gz ,,new-robot-comment/

Arch 忽略以两个逗号、等号和一些其他特殊字符开头的文件。通过在,,我们的变更集目录名称的开头,我们避免了 Arch 抱怨我们的新目录在存档中不存在的烦恼。在 tarball 文件名和变更集目录名称中使用您的电子邮件地址或其他标识符可能是很好的做法。

保持最新

您有时会想要下载项目的最新更改。这与运行tla update从检出的副本中一样简单。

Arch 首先运行tla undo以在应用新变更集之前搁置您的本地更改。一旦所有补丁都已应用,它会运行tla redo以重新应用您的本地更改。

上面介绍的所有 tla 命令都需要与托管存档的 lnx-bbc.org 系统建立正常运行的网络连接。对于断开连接的使用,您需要创建一个本地存档,然后在其中创建一个分支。

设置存档

在您可以开始在读写存档中工作之前,您必须向 tla 标识自己

$ tla my-id "J. Random Hacker <jrh@zork.net>"

一旦您输入了您的电子邮件地址,就可以为您的项目创建存档了。Arch 允许您创建许多存档,但您可以在同一个存档中保留任意数量的项目和分支。

存档名称由两部分组成,用两个连字符分隔:第一部分是您的电子邮件地址,第二部分是一些标识符。许多人喜欢使用四位数的年份作为标识符,并每年滚动到新存档

$ tla make-archive -l jrh@zork.net--2004 ~/ARCHIVE
$ tla my-default-archive jrh@zork.net--2004

my-default-archive命令使在本地存档上执行某些操作更容易键入。

设置项目分支

Arch 鼓励开发者使用分支来 fork 和合并项目。分支是将代码从一个存档移动到另一个存档的主要机制,即使是通过网络。您可以使用分支进行完整的代码 fork,以追求全新的开发路线,或者您可以使用分支在笔记本电脑上缓存项目副本,以便您可以在缺少网络访问的环境中工作一段时间。

已发布的分支也是使用 Arch 的开发者进行主要开发通信的机制。贡献者最有可能设置一个分支来做出本地更改,然后邀请上游开发者将这些更改合并回主项目,而不是通过邮件发送大型变更集 tarball 或补丁文件。这就是 Arch 设计的去中心化和民主化性质闪耀的地方。任何开发者都可以加入开发工作,而无需核心团队存档中的特殊权限。

在您可以分支 lnx-bbc 项目之前,您必须在您的存档中为项目设置一个空间。项目标识符的格式类似于存档名称的格式:类别(或项目名称)、两个破折号、分支名称、两个破折号和版本号。Tom Lord 作为 LISP 黑客的经验很可能影响了他使用这些破折号的决定

$ tla archive-setup lnx-bbc--robot-branch--0.0

这将创建一个名为 lnx-bbc 的类别,一个名为 robot-branch 的分支和一个名为 0.0 的版本。您无需在项目名称前面指定 jrh@zork.net--2004/,因为那是您的默认存档。

标记分支

最后,是时候从远程存档中标记分支了。这意味着 robot-branch 开始时是一个指向 lnx-bbc-devel@zork.net--gar 存档中特定项目版本的标签,并且所有本地更改都从该点开始

$ tla tag \
  lnx-bbc-devel@zork.net--gar/lnx-bbc--stable--2.1 \
  lnx-bbc--robot-branch--0.0

此时,运行tla abrowse应该显示您的默认存档如下

jrh@zork.net--2004
  lnx-bbc
    lnx-bbc--robot-branch
      lnx-bbc--robot-branch--0.0
        base-0
使用您的新分支

您现在可以检出您的新分支的副本了

$ tla get lnx-bbc--robot-branch robot-branch

此时,您可以进入 robot-branch 目录并进行一些更改

$ chmod 444 index.txt
$ tla mv faq.txt robofaq.txt
$ echo "ROBOT TIME" > robot-time
$ tla add robot-time
$ tla rm ports.txt

tla mv命令以 Arch 跟踪更改的方式重命名文件。重要的是使用此命令代替标准 mv。tla add命令准备将新文件插入存档,并且tla rm计划删除文件。

所有这些更改现在都可以签入到您的本地分支中

$ tla commit

您首选的文本编辑器(在 $EDITOR 环境变量中指定)将以签入日志的模板启动。一旦您填写了日志条目,保存并退出即可完成提交。

现在运行tla abrowse显示您在存档中有 robot 分支的两个修订版本,base-0 和 patch-1

jrh@zork.net--2004
  lnx-bbc
    lnx-bbc--robot-branch
      lnx-bbc--robot-branch--0.0
        base-0 .. patch-1

合并来自两个不同存档的项目

当然,当您在您的分支上工作时,原始存档上的开发可能仍在继续。运行tla update仅从您的本地分支而不是原始项目获取更改。要合并来自上游的更改,您需要star-merge:

$ tla star-merge \
lnx-bbc-devel@zork.net--gar/lnx-bbc--stable--2.1

如果发生冲突(您的分支和上游项目都对同一行代码进行了更改的情况),Arch 使用标准的 patch 方法为每个发生冲突的文件创建 .orig 和 .rej 文件。最好使用 find 实用程序在提交星形合并之前找出任何拒绝。

加速存档操作

您可能已经注意到,修订版本被命名为 base-0 或 patch-#,其中 # 是必须应用于 base-0 的补丁数。Arch 使用日志结构化存档格式,因此存档操作只会向项目中添加信息。这意味着对于具有许多修订版本的大型项目,某些任务可能需要很长时间。

为了加速操作,您可以创建给定修订版本的快照。Arch 快照只是检出修订版本的压缩 tarball。当执行检出或其他操作时,Arch 会查找编号最高的快照并从那里应用任何必要的补丁

$ tla cacherev

完成后,您可以运行tla cachedrevs以查看您的存档中哪些修订版本具有快照

lnx-bbc--robot-branch--0.0--base-0
lnx-bbc--robot-branch--0.0--patch-1

因为您并不总是拥有在存档中创建快照的权限,所以创建一个本地缓存来加速文件操作可能会很有用。Arch 提供了第二种缓存,称为库,它存储来自各种修订版本的检出文件的副本。这对于远程存档尤其有用,因为它意味着您甚至不需要在应用变更集之前下载基本快照修订版本

$ mkdir ~/LIBRARY
$ tla my-revision-library ~/LIBRARY
$ tla library-config --greedy ~/LIBRARY
$ tla library-add \
  lnx-bbc-devel@zork.net--gar/lnx-bbc--stable--2.1

这个库不小,截至 2004 年 6 月,上面的示例包含超过 78MB。然而,与慢速链接相比,其优势是值得付出努力的。此外,笔记本电脑通常具有慢速 ATA 硬盘驱动器,并且涉及的存档操作可能会很慢,因为驱动程序会占用大量 CPU 周期。一个贪婪的(自动更新的)Arch 库可以使您的版本控制操作更快、更灵敏,即使对于本地存档也是如此。

更多内容即将推出

在本系列的下一篇文章中,您将学习如何创建公开可用的镜像,以便上游开发者可以从您的分支星形合并回来。此外,您还将学习如何从繁忙的分支中挑选变更集,以及如何使用 GnuPG 对您的变更集进行加密签名以确保安全。

本系列的第三篇也是最后一篇文章将介绍使用 Arch 的集中式开发技术。您将学习如何使用 OpenSSH 的 SFTP 协议管理共享访问存档,以及如何编写脚本以在您的存档上执行自动化任务。

本文资源: /article/7752

Nick Moffitt 是居住在旧金山湾区的 Linux 专业人士。他是 GNU/Linux 的 LNX-BBC 可启动商务名片发行版的构建工程师,也是 GAR 构建系统的作者。在不进行黑客攻击时,他研究城市公共交通的历史。

加载 Disqus 评论