SlideShare une entreprise Scribd logo
1  sur  40
Subversion FAQ
本文根据原文 r33959,由 Subversion 中文站的中文化翻译小组翻译,欢迎各位参与翻译工作,加入地址:
http://code.google.com/p/svncndoc/。参与翻译的志愿者包括 rocksun、akeybupt2004、zhaozhi 和
jiaqifeng。

常见问题:

  •   为什么会有这样一个项目?
  •   Subversion 是私有软件吗?我听说它是属于 CollabNet 公司的。
  •   Subversion 用在我的项目上是否足够稳定?
  •   Subversion 的客户端/服务器在协同工作时的策略是怎样的?
  •   Subversion 可以运行在哪些操作系统上?
  •   所有它的一切是否是一种新的文件系统?比方说 ext2 文件系统?
  •   为了运行一个 Subversion 服务器,哪些硬件是我所需要的?
  •   我听说 Subversion 是 Apache 项目的扩展?我是否需要 Apache 来做服务器呢?
  •   是否意味着我必须首先安装 Apache 才能使用 Subversion?
  •   我现在所运行的是 Apache 1.x,但是我不能仅仅为了支持 Subversion 版本库而将其转换成 Apache
      2.0。这是否意味着我不能使用 Subversion 服务器?
  •   为什么不象 SCM 系统 Y 那样来做 X?
  •   为什么全部的库都使用相同的修订版本号码?我想让我的每一个工程都有其自己的修订版本号码。
  •   Subversion 有没有变更集?
  •   下一个版本什么时候发布?
  •   Subversion 是否支持符号链(symlinks)?
  •   我需要一个高分辨率的 Subversion Logo,从哪里可以得到它呢?
  •   我还有些其他的问题,我从哪里可以得到更多的相关信息?
  •   为什么我的邮件没有显示在邮件列表上?

如何使用:

  •   怎么样检出 Subversion 版本库里的代码?
  •   怎么样创建一个版本库?怎样将数据导入到版本库中?
  •   怎么样将已经存在于 CVS 版本库中的代码转换并导入到 Subversion 版本库中?
  •   我必须通过代理访问网络,我该怎么办?
  •   我的管理员不想让我有一个 Subversion 的 HTTP 服务器,那么如何做我才可以远程使用?
  •   如何在同一个版本库里管理几个不同的项目?
  •   我如何合并两个完全分开的版本库?
  •   我必须在 NFS 服务器上存储版本库/工作拷贝吗?
  •   为何我的版本库占去这么多的磁盘空间?
  •   我如何恰当的设置我的版本库的权限呢?
  •   为何只读的操作仍然需要版本库的写访问?
  •   如何完全的从版本库历史中删除一个文件?
  •   一个版本提交之后,如何修改其日志信息?
  •   怎么样向 Subversion 提交一个补丁?
  •   我如何进行“iplace”的导入(例如:向 Subversion 添加一个目录结构,而原先的数据直接成为工作拷
      贝)?
  •   人们在讨论升级 Subversion 时所说的“转储/加载(dump/load)”是什么?
  •   如何设置客户端通过使用 SSPI 认证的 Windows 域控制器进行认证?
  •   我不喜欢“.svn”这样的目录名字,而喜欢“SVN”或者其他一些目录名,我该如何改变呢?
  •   如何更改一个文件名的大小写?
  •   我不能象 CVS 那样使用标签将一个分支的变更合并到主干(trunk),可以吗?
  •   为什么$Revision$关键字不是我预想的那样?它替换的是文件最后修改的修订版本,但有时候我希望它
      能替换文件的当前修订版本。
  •   Subversion 是否有一个功能类似 CVS 的$Log$的关键字呢?
•   在我的工程里有一个文件,每个人都必须改变它,但是我不希望他们本地的修改被提交,如何让'svn
     commit'忽略这个文件?
 •   当我通过 svn+ssh 来访问一个版本库的时候,我的密码没有被缓存在~/.subversion/auth/,我应该如
     何避免每次都要键入密码?
 •   我的 svnserve 二进制程序不在我的用户的默认路径中,他们使用 svn+ssh,我不知道怎样修改他们的
     路径来让他们运行 svnserve。
 •   我希望允许通过 svn+ssh://来访问版本库,但我很忧虑。我讨厌为每个用户分配一个登录帐号的方法,
     那样我会为他们是否被允许访问我的机器感到担心。
 •   我怎么才能为版本库的所有文件设置一个的属性?另外,我该如何确保每个添加到版本库里的新文件都有
     这些属性?
 •   我如何处理编辑器路径中的空白?另外,如何定义编辑器的命令行选项?
 •   如何确定版本库正在使用的 Berkeley DB 的版本?
 •   我在版本库中管理了一个网站,如何才能实现每次提交之后站点自动更新?
 •   我如何检出一个单独的文件?
 •   如何在工作拷贝执行完添加、删除、拷贝和重命名操作之后检测这些操作?
 •   在 Windows 上如何将 svnserve 当作服务来运行?
 •   如何转换我的版本库,从 BDB 到 FSFS,或者从 FSFS 到 BDB?
 •   版本库如何处理二进制文件?
 •   如何让 svn diff 仅显示被改变的文件的名字,而不是连内容也显示出来?
 •   我能否用通配符或者点符号来一次性移动多个文件?
 •   我如何用 Subversion 维护一个第三方不断修正的软件呢?("供方分支")?

疑难解答:

 •   我的版本库经常看起来卡住了,一直报一个需要重新恢复(DB_RUNRECOVERY)的错误,怎么会导致这
     个问题?
 •   每次我想访问我的版本库,进程就会挂起。我的版本库坏掉了吗?
 •   我的版本库一直报告错误"Cannot allocate memory",我该怎么办?
 •   每当我试图运行一个 svn 命令时,都会提示我的工作拷贝已经被锁定了,是我的工作拷贝坏掉了吗?
 •   我试图去提交,但是 Subversion 提示我的工作拷贝已经过时。
 •   我为项目贡献了一个补丁,而这个补丁添加了一个新文件,现在 svn update 不能工作了。
 •   我刚刚编译了分发二进制程序,但是当我试图检出版本库时,我得到一个错误“Unrecognized URL
     scheme”。这是怎么回事呢?
 •   当我查找或打开一个版本库时出现错误,但是我知道我版本库 URL 是正确的,哪里出错了?
 •   当我运行‘configure’命令时,出现一些错误 subs-1.sed line 38: Unterminated `s' command,这
     是怎么回事?
 •   我在 Windows 下用 MSVC++6.0 构建 Subversion 时候有些麻烦,我该怎么办?
 •   如何在 file:协议的 URL 中指定 Windows 盘符?file: URL?
 •   我在通过网络对 Subersion 版本库进行写操作的时候有些麻烦。
 •   VS.NET/ASP.NET 在处理".svn"目录名时好像有些问题,我该怎么办?
 •   在 Windows XP 下,Subversion 服务器有时候会发布一些错误数据,真的是这样吗?
 •   在 Subversion 服务器和客户端之间进行交互时,跟踪网络的最好方法是什么?
 •   为什么 svn revert 要求有一个明确的目标?为什么它默认不是递归执行的呢?这与所有其他的子命令都
     不同。
 •   当我启动 Apache 时,mod_dav_svn 报告"bad database version",它发现的是 db-3.X,而不是
     db-4.X。
 •   在 Red Hat 9 上,我得到一个"Function not implemented"错误,一切都停止工作。我该如何修正它
     呢?
 •   为什么在文件在通过 Apache(ra_dav)被提交和导入时,SVN 的日志说"(no author)"?
 •   我在 Windows 平台上偶尔会得到一个"Access Denied"错误,它的发生好像没有什么规律,为什么呢?
 •   在 FreeBSD 上,某些操作(尤其是 svnadmin create)有时候会被挂起。为什么?
 •   我可以从一个 WEB 浏览器上查看我的版本库,但是在执行'svn checkout' 时发生一个错误:"301
     Moved Permanently"。那个地方出错了?
 •   为什么 HTTP 的 Digest 认证不能工作?
 •   在 AIX 上通过 xlc 编译文件,出现了一些编译错误?怎么回事呢?
•   我用非递归方式(通过-N 选项)检出了一个目录,现在我想让某个子目录“出现”,但是 svn up subdir
      不起作用。
  •   我试图在 Win32 平台 Apache 服务器上使用 mod_dav_svn,但是我得到找不到 module 的错误,而
      mod_dav_svn.so 文件确实处在Apachemodules 下。
  •   为什么我的版本库钩子不工作?
  •   为什么我的--diff-cmd 会有关于‘-u’的报错,我想用--extensions 去覆盖它,但是不起作用。
  •   啊!我发现我的 Subversion 客户端在磁盘上以纯文本的形式缓存了密码!啊!
  •   我得到一个错误"svn: bdb: call implies an access method which is inconsistent with previous
      calls"。我该如何修正它呢?
  •   我无法热备份我的版本库,当文件大于 2Gb 时 svnadmin 会出错。
  •   我看不到我刚刚提交的文件的日志记录,为什么呢?
  •   升级到 Berkeley DB 4.3 或更新的版本之后,版本库出错了。
  •   当我通过 http://从 MacOS X 10.4 (Tiger)的平台上检出版本库的时候,为什么偶尔会得到一些不一致
      的错误?
  •   我不能构建 Subversion,我的工作拷贝源码在 Debian GNU/Linux 上,在链接阶段我得到了一些错
      误,哪里错了呢?
  •   我在使用 FreeBSD,并且已经启动了 svnserve,但是看起来并没有监听 3690 端口。
  •   我不能添加一个目录,因为 Subversion 说“它已经处于版本控制了”。
  •   有时候通过 svnserve 访问一个非公开的版本库实在是太慢了。
  •   当执行的 Subversion 操作需要通过 SSL 传递大量数据的时候,碰到一个错误 SSL negotiation failed:
      SSL error: decryption failed or bad record mac。
  •   我得到一个错误"This client is too old"。
  •   为什么有时候 svn switch 不能工作?
  •   在 Windows 平台上,通过命令行客户端的执行更新操作时,我碰到一个错误"The system cannot find
      the path specified",并且提示说我的工作拷贝可能损坏了,但是我能通过 TortoiseSVN 更新时完全正
      常,这是怎么回事呢?
  •   我碰到一个错误"This client is too old to work with working copy '...' ",不升级 Subversion 能够
      解决吗?
  •   当我在 64 位 Linux 上编译 Neon 库时,发生一个错误"relocation R_X86_64_32 against `a local
      symbol' can not be used when making a shared object"。
  •   为什么从 Apache 检出时得到“Could not read response body: Secure connection truncated”的
      错误?

开发者问题

  •   怎样在 RAM 磁盘上进行回归测试?
  •   怎样在不安装的情况下对动态 Subversion 库运行调试器?
  •   怎样让编译器不内联混淆(inlining obfuscating)源代码的情况下对 Subversion 库运行调试器?

说明:

  •   Subversion 用到的 HTTP 方法是有哪些?
  •   什么是'bikeshed'?
  •   你是怎样读"Subversion"的?
  •   什么是'baton'?
  •   当你说版本库是'楔住(wedged)'的时候,是什么意思?


常见问题:

为什么会有这样一个项目?

为了接管 CVS 的用户基础。确切的说,我们写了一个新的版本控制系统,它和 CVS 很相似,但是它修正了以前
CVS 所没有解决的许多问题。请看我们的首页。
Subversion 是私有软件的吗?我听说它是属于 CollabNet 公司的。

不是,Subversion 一款开源/免费的软件。CollabNet 公司为几个全职的开发人员支付薪水,并且拥有相关代码
的版权,但是这个版权是一个 Apache/BSD-风格的许可证,它完全遵从于 Debian Free Software
Guidelines。换句话说,你可以随心所欲的去下载,修改,或者重新发布新的版本,而不需要经过 CollabNet 公
司或者其他任何一个人的许可。

Subversion 用在我的项目上是否足够稳定?

是的,绝对可以。它是一款已经准备好进入黄金时段的产品。

Subversion 从 2000 年开始开发,在一年之后成为一个自足执行(self-hosting)的项目。在之后的一年,当我们
将其称 为"alpha"版本的时候,Subversion 已经被很多的个人开发人员所使用,并确实发挥了真正的作用。在那
之后,有两年多的时间被用来进行 Bug 追踪(bugfixing)和增强稳定性(stabilization),直到我们发布了 1.0 版
本。大多数的其它项目可能都会把产品的“1.0”版本叫 做早期版本,但是我们故意的尽可能长的推迟了这个版本
的发布。我们意识到很多人在他们最初使用了 Subversion 之后一直在等待 1.0 版本的发布,并 且对这个意义非
凡的版本有着特别的期待,所以我们在这样一个版本上用了很多的时间而不至于让他们失望。

Subversion 的客户端/服务器在协同工作时的策略是怎样的?

客户端和服务器被设计成只要他们相互之间没有超过一个主要的发行版本,就可以协调工作。例如任何一个 1.x
的客户端都可以和一个 1.y 的服务器协调工作。然而,如果客户端和服务器的版本不相匹配,某些特性可能不能
使用。

客户端和服务器之间的兼容性策略记录在 Hacker's Guide to Subversion 的“兼容性”一节里面。

Subversion 可以运行在哪些操作系统上?

所有现代风格的操作系统,比如 Unix, Win32, BeOS, OS/2, MacOS X。

Subversion 是用 ANSI C 来写的,并且使用了 APR,也就是 Apache Portable Runtime 库 作为可移植
层。Subversion 的客户端将可以运行在任何 APR 运行的地方,这是最重要的一点。Subversion 服务器(例
如,版本库端)同样, 唯一的例外是在 Berkeley DB 的 Win9x(Win95/Win98/WinME)作为平台的主机上,因
为 Berkeley DB 在 Win9x 平台上共享存储器的有段问题。FSFS 版本库(从版本 1.1 开始引入)没有这种限制;
然而由于 Win9x 对文件锁定的支持限制,他们仍然 不能在 Win9x 的平台上工作。

重申一下,Subversion 客户端可以运行在任何 APR 所运行的平台上。Subversion 服务器也可以运行在任何
APR 平台所能运行的平台,但是不能在 Win95/Win98/WinMe 上管理版本库。

所有它的一切是否是一种新的文件系统?比方说 ext2 文件系统?

不是。"Subversion 文件系统"不是一个可以装在操作系统上的内核级的文件系统,相反,它是 Subversion 版本
库的接口,是一个版本 文件系统,在某种意义上说,它可以存储一个文件目录结构(树)并且使这个目录结构从
一个修订版本到下一个修订版本的过程中保留版本信息。访问这个版本库来 编写程序和使用其他文件系统的 API
是很相似的,但是最大的不同在于,这个特殊的文件系统在你写入的时候不会丢失数据。目录结构(树)的一些旧
的状态信息 可以被很容易的恢复,就像恢复到最近的状态那样容易。

为了运行一个 Subversion 服务器,哪种硬件是我所需要的?

运行 Subversion 服务器要依赖各方面的多种因素,比如说一定数量的用户,经常性的提交,其它相关联的服务
器,版本库的大小以及自定义版本库 的负载等。当使用 Apache 时,有可能 Apache 本身在内存的使用情况将成
为最大的制约因素。请参阅邮件列表上对这个问题的讨论,这里有针对这个问题的明确的答案。
需要记住的是,在同一台服务器上运行其它的应用程序,比如版本库的浏览器同样会使用内存,它是独立于
Subversion 本身。

通常,和 CVS 本版库相比,你可以期望需要更少的服务器内存。

我听说 Subversion 是 Apache 项目的扩展?我是否需要 Apache 来做服务器呢?

不用。Subversion 是一系列的库,它与一个命令行的客户端相互配合工作。有两类不同的 Subversion 的服务器
进程,包括一个 svnserve 进程,这是一个小的类似 CVS 的 pserver 进程的独立运行程序,另一个是使用
mod_dav_svn 模块的 Apachehttpd-2.0。svnserve 进程可以说是一个常用协议,而 mod_dav_svn 进
程使用了 WebDAV 作为它的网络协议。请参阅 Subversion 手册第六章以了解更多的内容。

是否意味着我必须首先安装 Apache 才能使用 Subversion?

一句话:不必。

详细的回答是:如果你仅仅是想去访问一个版本库,你只需要构建一个 Subversion 的客户端。如果你想拥有一
个网络的版本库,那么你需要安装 Apache2 或者一个“svnserve”服务器。

关于安装一个可以访问的 Subversion 服务器的详细信息,请参阅:Subversion 手册第六章。

我现在所运行的是 Apache 1.x,但是我不能仅仅为了支持 Subversion 版本库而将
其转换成 Apache 2.0。这是否意味着我不能使用 Subversion 服务器?

不必,你可以用 svnserve 作为 Subversion 的服务器,它可以很好的工作。

在使用 Apache server 时,如果你想使用分布式创作和版本管理协议(WebDAV)和所有其他一些好的功能特
性,那么是的,你需要 Apache 2.0。但是不管怎样,当你继续在 80 端口运行 Apache1.0 的时候,你总是可以
在另外一个不同的端口运行 Apache2.0。不同版本的 Apache 可以在同一台机器上很好的和平相处。仅仅需要在
改变 httpd.conf 文件中把 Listen 指令从 80 改成 8080,或者其他你想要改成的端口。然后确保在你公布版本库
的 URL 的时候加以说明:(例如,http://svn.mydomain.com:8080/repos/blah/trunk/)。

为什么不象 SCM 系统 Y 那样来做 X?

我们从来没有试图在 SCM 系统上推到重来,开辟出一个新的天地,也没有试图完全模仿每一个 SCM 系统的好的
特性,我们只是要取代 CVS。请参阅我们的第一个问题。

为什么整个库都使用相同的版本号码?我想让我的每一个工程都有其自己的版本号。

首先,请注意 Subversion 没有项目这个概念。版本库只是存储版本化的目录树 — 你可以将某个子目录当作项
目,但是 Subversion 不会对其特殊对待。因此,对于一个项目的构成完全由用户自己解释。(与之类似的
branches 和 tags 的习惯是建立在复制之上,而不是建立在 Subversion 的概念之上。)

每当你提交变更时,版本库会在版本库目录树整体上增加一个修订版本,并将新的树赋予一个新的修订版本号,
当然,大多数目录树和前一个修订版本完全一样,只是部分被更改。

新修订版本号码是一个顺序增加的标签,会附加给每个新增的树,而不是这个修订中的某个文件或目录,然而,
通俗来说,会使用修订版本号码来引用修订中 提交的变更;例如“r588 中的变更”(“r588”是“修订版本 588”的
简写)的真实含义是“版本库目录树 587 和 588 的区别”,或者是另一个说法 “将目录树 587 变成 588 的变更”。
因此,不断增加的修改版本号码会以一个整体标示版本库的进展;你通常不会使用修订版本号码来度量版本库中
特定项目的进展,当然,修订版本号码不应该作为项目可见的发布号码,对此,你应该通过其他机制来区别发
布,例如使用 tags。

Subversion 是否有变更集?

这个问题有些麻烦,因为好像每个人对变更集的定义多少有些不同,或者至少对版本控制系统的变更集特性多少
有些不同的期望。

基于这个讨论的目的,这里对变更集有一个简单的定义:它是所有改变的唯一的名字的集合,这些改变可能包括
对文件内容句法的编辑,目录结构的改变,或者是一些元数据的重新组合。更加通常的理解,一个变更集仅仅是
一个你所能进行参阅的补丁的名字。

Subversion 按照一阶对象的方式管理版本化目录树(版本库是一个目录树数组),而变更集则是被推生出来的东
西(通过比较相邻的目录树)。 Arch 或 Bitkeeper 这类程序以相反方向创建:他们用一阶对象的方式管理变更
集(版本库是一系列的补丁),而目录树则是由一系列的补丁组合而成。

从根本上来说,两者都不够好:争论至少可以追溯到三十年以前。对于不同类型的软件开发,各有利弊。现在我
们不打算讨论这些,这里我将解释使用 Subversion 能怎么做。

用 Subversion,用一个全局的版本编号 N 来命名版本库目录树:这是说版本库是经过第 N 次提交。它还包括一
些不明显的变更集:如果你比较目录树 N 和目录树 N-1,你可以精确得到提交的补丁。

因此,可以很容易的想到,版本 N 不仅仅是一个变更集。如果你用一个事件追踪去管理 bug,你可以用版本号码
去引用特殊的补丁,这些补丁很适合 bug。例如,“这个事件被稳定在 9238 版本。”一些人可能运行‘svn log
-r9238’来阅读对应 Bug 的补丁信息,运行‘svn diff -r9237:9238’来查看补丁本身。svn 合并命令也是利用了
版本号码。只要在合并参数中指明结果集,就可以把结果集从一个分支明确的合并到另一个 分支:‘svn merge -
r9237:9238 branchURL’将合并结果集#9238 到你的工作拷贝。

似乎根据结果集构建和主要对象的构建一样复杂,但是已经比 CVS 方便许多了。

下一个版本什么时候发布?

看我们的状态页 http://subversion.tigris.org/project_status.html。

Subversion 是否支持符号链?

Subversion 1.1(和后续版本)已经可以把一个符号链置于版本控制之中,通过一个常用的 svn add 命令即
可。

详细:版本库还没有一个关于符号链的内部概念,它存储一个附加'svn:special'属性的普通文件作为“符号链
接”。svn 客户端(在 unix 上)可以看到属性,并且在工作拷贝里转换成一个符号链。Win32 没有符号链,所以
一个 win32 的客户端不会做任何的转换:对象表现的像一个平 常的文件。

我需要一个高分辨率的 Subversion Logo,从哪里可以得到它呢?

可用的矢量 Subversion logo 在 Subversion 版本库的 www 文件夹下可以得到。

特别的是,EPS 版本,和一个 Adobe 插图文档也是可用的。
我还有其他的一些问题,我从哪里可以得到更多的信息呢?

如果你在阅读这个常见问题回答之后,没有找到你问题的答案,那么你还有其他的几个资源可以利用:

  •   Subversion 手册,以及中文手册 Subversion 手册
  •   The Subversion 用户邮件列表 (users@subversion.tigris.org) — 注意这个列表需要经过审核,所以
      在显示之前有一些延迟。
  •   Subversion 用户信息列表。
  •   在线聊天系统(IRC)在 irc.freenode.net 的#svn 频道。
  •   svnforum.org 一个非官方基于网络的论坛,针对的读者和邮件列表近似。

为什么我的邮件没有显示在邮件列表上?

我们的邮件列表为了保持在一个适度的标准,所以你最初的邮件可能会被延迟通过,直到维护人员有机会让它通
过。一旦邮件允许通过,所有从相同的地址挂起的邮件将被自动支持,所以你应该不会再被拒绝。当然,如果你
的发送地址改变了的话,你将不得不再次让维护人员检测通过。


如何:

我如何才能检出 Subversion 版本库里的代码?

使用 Subversion 客户端:      $ svn co http://svn.collab.net/repos/svn/trunk subversion

这将会从 Subversion 源文件目录里检出一个名叫 subersion 的目录到你的本机上。

我如何创建一个版本库呢?并且我又该如何向里导入数据呢?

请参阅 http://svn.collab.net/repos/svn/trunk/README;特别的,在第 IV 部分,即“快速指南”。

更详细的资料,请阅读 Subversion 手册第五章。

我如何把一个现存的 CVS 版本库转换成 Subversion 版本库?

试一下 cvs2svn 转换工具,从 http://cvs2svn.tigris.org/ (或者从这里 特性列表和相关文档)。cvs2svn 是大
多数人的选择,但是如果有别的原因使他不能满足你的要求,至少还有其他两种工具供你选择:

  •   一个是基于 VCP,由 Chia-liang Kao 编写,可以在 CPAN 找到。
  •   另一个由 Lev Serebryakov 写的 refinecvs,在 http://lev.serebryakov.spb.ru/refinecvs/上面可
      以找到。

也可以参阅 Subversion 链接页面。

我必须通过代理访问网络,我该怎么办?

Subversion 支持通过代理访问网络。首先,修改配置文件中的"servers"部分,并指定你的代理服务器。配置文
件所在目录在不同的操作系统上可能不同,在 Linux 或 Unix 系统中,通常是~/.subversion;在 Windows 系统
中,通常是"%APPDATA%Subversion"。(执行"echo %APPDATA%"显示目录的具体路径,注意这是一个
隐藏目录。)

配置文件中的注释描述了配置文件书写的格式。如果配置文件还不存在,可以取得最新版的 svn,并执行任何
svn 命令,这将创建配置文件模板及其相应的目录。
其次,请确认你的代理服务器支持所有 Subversion 必须的 HTTP 方法。有些代理服务器默认不支持以下命令:
PROPFIND, REPORT, MERGE, MKACTIVITY, CHECKOUT。解决办法依赖于你使用的代理服务器软件,对于
Squid,配置选项如下:         # TAG: extension_methods


  #       Squid only knows about standardized HTTP request methods.
  #       You can add up to 20 additional "extension" methods here.
  #
  #Default:
  # none
  extension_methods REPORT MERGE MKACTIVITY CHECKOUT

(Squid 2.4 及其之后的版本支持 PROPFIND.)

参见"Subversion 用到的 HTTP 方法是有哪些?"来配置代理服务器来支持 HTTP 方法。

如果让代理服务器支持 Subversion 访问网络很困难甚至是不可能的话,而你只想 checkout Subversion 的源
代码,你可以绕过代理服务器。一些代理服务器封锁了 80 端口,如果是这样的话,可以通过 81 端口访问
svn.collab.net 代码库服务器。执行:  svn checkout http://svn.collab.net:81/repos/svn/
trunk subversion

可能代理服务器会放行。另一个办法是通过 SSL 来 checkout,SSL 被大部分代理服务器所支持:                  svn
checkout https://svn.collab.net/repos/svn/trunk subversion

当然,你的 svn 客户端应该支持 ssl。在编译源代码的时候,在./configure 时添加--with-ssl 选项。执行 svn --
version 可以知道你的 svn 是否支持'https'。

我的管理员不想让我有一个 Subversion 的 HTTP 服务器,那么如何做我才可以远程
使用?

一个简单的选择是使用 svnserve 服务器来代替。请参阅 SVN 手册第 6 章中的详细内容。

然而,如果你的管理员不希望你运行 Apache,这很可能是他们不想让你在 3690 端口运行一个客户服务器,则备
选答案是假定你的管理员同意你使用现有的 SSH 设施。

如果你使用 CVS,你可能已经使用 SSH 来登录 CVS 服务器,ra_svn Subversion 的访问方法是和使用
Subversion 是相同的。仅仅是在你的版本库的 URL 上加上一个"svn+ssh"的前缀。 $ svn checkout
svn+ssh://your.domain.com/full/path/to/repository

这将使你的 SSH 的程序在远程运行一个私有的'svnserve'进程,用你的用户 ID 访问版本库,并通过加密管道将
数据传递回来。

然而,另外的一种可以用来替代的解决方案是将 SSH 端口转向连接到通过 ra_dav 保护的服务器上。你可以通过
SSH 连接到一个防火墙后的一个机器,这个机器可以访问 Subversion 服务器。注意,这个 SSH 服务器不需要
与 Subversion 安装在同一个机器上,可以是,但不是必须是。

然后你可以创建一个本地端口来连接在你家里的 Subversion 版本库的 HTTP 服务器。你可以通过本地端口’连
接‘Subversion 版本库。然后,请求将被通过 SSH 服务器’通道‘发送到你的 Subversion 服务器。

一个示例:在你们公司位于 10.1.1.50(叫它 svn-server.example.com)的防火墙后面设置了一个
Subversion ra_dav,你的公司允许 SSH 通过公共方式访问 ssh-server.example.com,而在内部可以通过
http://svn- server.example.com/repos/ours 访问 Subversion 版本库。
实例:那么客户端通过端口转向连接 ssh 服务器,并通过端口转向检出 % ssh -L 8888:svn-
server.example.com:80 me@ssh-server.example.com


% svn checkout http://localhost:8888/repos/ours

请注意 svn-server.example.com 也可以让 httpd 实例被非信任用户运行在无特权的端口上,这允许
Subversion 不需要 root 访问权限。

Joe Orton 注明 服务器对正在使用的 MOVE 和 COPY 请求头的主机名字是很敏感的,所以这个地方你必须要小心
—工作正常可能需要配置"ServerAlias localhost"。

一些 SSH 端口转向的链接

  •   http://www.onlamp.com/pub/a/onlamp/excerpt/ssh_11/index3.html
  •   http://csociety.ecn.purdue.edu/~sigos/projects/ssh/forwarding/
  •   TTSSH: A Win32 SSH client capable of port forwarding

我如何在 Subversion 下面管理几个不同的项目?

这决定与你的项目的复杂度,如果你的项目是相关的,并且有可能要共享数据,那么最好的方式是通过子目录创
建一个版本库。像下面这样子:    $ svnadmin create /repo/svn


      $ svn mkdir file:///repo/svn/projA
      $ svn mkdir file:///repo/svn/projB
      $ svn mkdir file:///repo/svn/projC

如果你的工程是完全不相关的,并且他们之间不可能共享数据,这样最好创建几个独立的完全不相关的版本库。
    $ mkdir /repo/svn


      $ svnadmin create /repo/svn/projA
      $ svnadmin create /repo/svn/projB
      $ svnadmin create /repo/svn/projC

这两种方式之间不同之处在于: (由 Ben Collins-Sussman 解释 <sussman@collab.net>):

  •   在第一种情况之下,代码可以很容易的在两个项目之间拷贝和移动,并且操作的历史记录会被保存下来。
      ('svn cp/mv'现在只能在单个版本库中工作。)
  •   因为修订版本号是版本库范围的,在第一种情况下,对任何项目的提交都可能造成全局的版本冲突。所以
      如果有个人检出了‘projB’,并发现已经发生的 10 次修订,但是 projB 没有完全改变,这看起来有些奇
      怪。事实上,这无关紧要,只是一开始会感到有些奇怪。这就像每当人们向 rapidsvn 提交,而
      rapidsvn 和 svn 在同一个版本库之下时,svn 的状况。:-)
  •   第二种情况可能更利于安全管理吗;可以很容易的使用 Apache 访问控制将每个项目隔绝(就用户和许可
      的角度来讲)。在第一种情况下,你需要在版本库放一 个钩子脚本来区分不同的项目(“是否允许用户在
      特定的子目录提交?”)当然,我们已经准备了这些脚本供你使用。

我如何合并两个完全分开的版本库?

如果你不在意某个版本库的完全历史,你可以只是在某个版本库为另一个项目创建一个新的目录,然后导入另一
个项目。
如果你在意两边的历史,那么你可以使用'svnadmin dump'将一个版本库的内容转储出来,然后使用'svnadmin
load'加载到另一个版本库。原来的修订版本号码会取消,但你还有历史。


 Peter Davis <peter@pdavis.cx>也解释了一种方法,可以使用像 CVS 模块那样使用 svn:


只要合并发生在不同的目录树,你可以使用 svn 版的 CVS 模块。

将 svn:externals 属性设置到从其他版本库检出的目录上,无论原来的目录是何时检出的。版本库还是分离的,
但是从工作拷贝的角度看,他们好像合并了。如果你在导入的目录中提交,也将会影响外部版本库。

合并并不意味着完全的干净:导入只是影响了工作拷贝,所以你应该不能使用第一个版本库的 URL 访问从第二个
导入的模块,他们都还是有各自的 URL。

也可以看 miscellaneous utilities,里面有一些在合并不同版本库时帮助选择和重排序修订版本的工具,特别如
基本操作的 perl 脚本 svn-merge-repos.pl 和高级组织的 python 类 SvnDumpTool。

我必须在 NFS 服务器上存储版本库/工作拷贝吗?

如果你使用 Berkeley DB 作为版本库的后端(在 Subversion 1.0 和 1.1 这是默认值,此后不是默认值),我们
建议你不要将 版本库存放在远程文件系统(例如,NFS)。虽然 Berkeley DB 数据库和日志文件可以存放到远
程文件系统,但是 Berkeley DB 的共享区域文件不可以放到远程文件系统上,所以版本库只有被一个文件系统客
户访问时才能保证安全,而且那种情况下并不是所有的 Subversion 功 能都在一个客户下工作正常。

如果你使用 FSFS 作为后端,那么将版本库存放到 NFS 服务器(应当是支持锁定的服务器)也应当没问题。

工作拷贝可以存放到 NFS(一个常见的场景是你的主目录在 NFS 服务器上)上,在 Linux NFS 服务器上,因为
在检出时 Subversion 内部使用的重命名的量比较大,一些用户报告应当关闭‘子目录检查(subtree
checking)’应当关闭,如果关闭子目录检查的详细信息可以看 NFS Howto Server Guide 和 exports(5)。

我们至少接到一份对于通过 SMB 访问造成工作拷贝楔住的报告,造成错误的服务器是版本非常老的
Samba(2.2.7a),在新版本(3.0.6)Samba 中并没有再出现这个问题。

为何我的版本库占去这么多的磁盘空间?

在 Berkeley DB 环境中,版本库会在 repos/db/子目录存放所有的数据,这个环境会包含一组表和一组日志文件
(log.*)。Berkeley DB 会记录对表所作的变更,这样在出现中断后能够恢复到一致的状态(more info)。

如果你放任不管(作为版本库管理员),日志文件会不断的生长,吞噬磁盘空间。在任何时刻,Berkeley DB 只
使用很小一部分的日志文件(可以看这个帖子以及相关的线索);其余的可以安全的删除。如果你永久保存所有
的日志文件,理论上 Berkeley DB 能够根据这个文件回到出生的时刻。但是在实践中,如果你进行了备份,就没
有必要在磁盘中浪费空间了。

可以使用 svnadmin 查看哪些日志文件可以删除,你可以通过 crob 程序完成这个任务。 $ svnadmin list-
unused-dblogs /repos


/repos/db/log.000003
/repos/db/log.000004
[...]

$ svnadmin list-unused-dblogs /repos | xargs rm
# disk space reclaimed!
你也可以使用 Berkeley DB 的 db_archive 命令: $ db_archive -a -h /repos/db | xargs rm


# disk space reclaimed!

还可以看 svnadmin hotcopy 或 hotbackup.py。

注意:如果你正在使用 Berkeley DB 4.2,Subversion 创建的版本库会自动删除日志文件,如果你想关闭这个
功能,可以在 svnadmin create 命令中使用--bdb-log-keep 选项。可以参考 Berkeley DB 手册中的
DB_LOG_AUTOREMOVE 参数。

我如何恰当的设置我的版本库的权限呢?

试图保证尽可能少的用户能够访问版本库,例如以某个用户运行 apache 或'svnserve -d',那么版本库由这个用
户完全拥有。不允许任何其他的用户通过 file:///的 URL 访问版本库,必须只让拥有版本库的用户运
行'svnlook'和'svnadmin'。

如果你的客户端通过 file:///或 svn+ssh://访问,则无法避免多个用户的访问。在那种情况下,可以阅读第 6 章
最后一小节,看一下最下面工具栏的“检查列表”,它总结了让这个场景更安全的步骤。

SELinux / Fedora Core 3+ / Red Hat Enterprise 的用户注意:

作为标准 Unix 许可的补充,在 SELinux 下,每个文件、目录和进程都有一个‘安全上下文’。当进程试图访问一个
文件时,除了检查 Unix 访问许可,系统还会检查进程的安全上下文与文件的安全上下文是否兼容。

而 Fedora Core 3,随 SELinux 一起安装,在默认情况下 Apache 会在一个限制的安全上下文中运行。为了在
Apache 下运行 Subversion,你必须设置版 本库的安全上下文使之支持 Apache 的访问(或者关闭对 Apache
的限制,如果你认为这是过分小心)。chcon 命令可以用来设置文件的安全上下文(与 chmod 设置 Unix 访问许
可类似)。例如,一个用户可以这样运行命令             $ chcon -R -h -t httpd_sys_content_t
PATH_TO_REPOSITORY

设置安全上下文可以成功的访问版本库。

为何只读的操作仍然需要版本库的写访问?

某些客户端操作是“只读的”,例如检出和更新。从访问控制的角度,Apache 会这样处理。但是 libsvn_fs(版本
库文件系统 API)在生成增量树的时候还是需要写临时数据,所以访问版本库的进程应该能够读写访问 Berkeley
DB 的文件,才能完成功能。

尤其是版本库需要应答许多比较两个目录树的“只读”操作时,一个树可能是 HEAD 修订版本,而另一个则是临时
的事务-目录树 -- 因此许多写权限。

这种限制只存在于 Berkeley DB 后端;FSFS 后端并没有显示这种特性。

如何完全的从版本库历史中删除一个文件?

有某些特殊情况下,你可能希望完全的删除你曾经提交文件的所有信息(或许有人意外的提交了一份保密的文
档)。但是这个操作不是很容易完成,因为 Subversion 有意被设计成决不丢失信息,修订版本是基于上一个版
本所构建的不可改变(immutable)的文件树。从版本的历史记录里删除一个 修订版本将会造成多米诺骨牌效
应,造成后继版本的混乱,还有可能使得所有的工作拷贝无效。

项目有计划在未来实现一个 svnadmin obliterate 命令,能够完成永久删除信息的任务(可以看 issue
516。)
现在,你只有求助于你版本库的 svnadmin dump 命令,将转储文件经过 svndumpfilter 过滤(排除错误的
路径)传递给 svnadmin load 命令,请参阅 Subversion 手册第五章的相关详细信息。

一个版本提交之后,如何修改其日志信息?

日志信息作为每个修订版本的附加属性保存在版本库,默认情况下,日志信息属性(svn:log)不能在提交后修
改。这是因为对于修订版本属性(svn:log 是其中一个)的修改会导致以前的属性永久的消失,Subversion 会防
止这种意外情况发生。但是,还是有一些方法可以修改修订版本属性。

第一种方法是让版本库管理员允许修订版本属性修改,这可以通过创建"pre-revprop-change"(更多相关细
节可以看 Subversion 手册的这个小节)。钩子"pre-revprop-change"可以在修改之前访问老的日志信息
(例如,通过发送一个邮件),所以可以以某种方式保存它(例如,通过发送邮件)。一旦开启了修订版本属性
修改,你可以通过 svn propedit 或 svn propset 的--revprop 选项修改修订版本属性,就像下面这个: $
svn propedit -r N --revprop svn:log URL


$ svn propset -r N --revprop svn:log "new log message" URL

这里 N 是希望修改的日志信息的修订版本号码,而 URL 是版本库的位置。如果你从工作拷贝运行这个命令,你可
以省略 URL。

第二种方法是通过 svnadmin setlog 修改日志信息。这必须通过引用版本库的文件系统位置来执行,你不能使
用这个命令远程修改版本库。 $ svnadmin setlog REPOS_PATH -r N FILE

这里 REPOS_PATH 是版本库的位置,而 N 是你希望修改日志信息的修订版本,而 FILE 是包含新日志信息的文
件。如果"pre-revprop- change"钩子不存在(或者因为钩子脚本的原因你希望绕过),你还是可以通过--
bypass-hooks 选项实现。然而,如果你要使用这个选项,要 非常小心。你会绕过诸如变更的邮件提醒,或者保
存修订版本属性的备份系统。

怎么样向 Subversion 提交一个补丁?

首先,看一下 Hacker's Guide to Subversion。

一旦你消化了这些内容,可以在 dev 邮件列表发送一个题目有[PATCH]的邮件,并在邮件中包含你的补丁(除非
你的邮件客户端会完全处理它),不久之后就会有提交者捡起来,应用它(作出合适的格式化或内容变更),并
将其检入。

基本的过程看起来如下:             $ svn co http://svn.collab.net/repos/svn/trunk subversion


     $ cd subversion/www

            [ make changes to faq.html ]

     $ svn diff faq.html > /tmp/foo

     $ Mail -s "[PATCH] FAQ updates" < /tmp/foo

当然,你的邮件应当包含补丁完成什么功能的解释,按照 Hacker's Guide to Subversion 所说的,但是你已经
知道了,因为在你 Hack 之前已经完全阅读和理解,不是吗?:)
我如何进行 “iplace”的导入(例如:向 Subversion 添加一个目录结构,而原先的数
据直接成为工作拷贝)?

例如,假设你希望把/etc 下的一些文件纳入版本控制:                        # svn mkdir file:///root/svn-
repository/etc 


             -m "Make a directory in the repository to correspond to /etc"
       #   cd /etc
       #   svn checkout file:///root/svn-repository/etc .
       #   svn add apache samba alsa X11
       #   svn commit -m "Initial version of my config files"

这里利用了 svn checkout 的一个非立即但明显的优势:你可以从版本库直接检出一个目录到已存在的目录,这
里,我们首先在版本库创建一个目录,然后将其检出到已存在的目录/etc,将/etc 目录变成工作拷贝。一旦完
成,你可以使用普通的 svn add 命令选择文件和子目录进入版本库。

这是 svn import 的一个增强问题,它本应该能够在导入目录树时自动创建工作拷贝;可以看 issue 1328。

人们在讨论升级 Subversion 时所说的 “转储/加载(dump/load) ”是什么?

Subversion 的版本库数据库模式在开发中会偶尔改变,使用 1.0 以前的 Subversion 开发版本创建的老版本库在
升级时需要如下操作。如果在发布 X 和 Y 之间的模式发生变更,则版本库管理员升级到 Y 的时候必须如下操作:

  1.    关闭 svnserve、Apache 和任何可能访问版本库的东西。
  2.    使用版本 X 的 svnadmin 执行 svnadmin dump /path/to/repository > dumpfile.txt 。
  3.    mv /path/to/repository /path/to/saved-old-repository
  4.    现在升级到 Subversion Y(通过构建和安装 Y,替换 X)。
  5.    使用版本 Y 的 svnadmin 执行 svnadmin create /path/to/repository。
  6.    在使用版本 Y 的 svnadmin 执行 svnadmin load /path/to/repository < dumpfile.txt 。
  7.    从老版本库拷贝钩子脚本等到新版本库。
  8.    重启 svnserve、Apache 等等。

关于转储和加载的更多信息可以看 Subversion 手册的这个小节。

注意:大多数 Subversion 的升级不会需要转储和加载,如果某个版本需要,新版本的发布声明和 CHANGES 文
件会显著说明这一点。如果你没有看到这个说明,那么应该是没有模式变更,也就没有转储/加载的必要。

如何设置客户端通过使用 SSPI 认证的 Windows 域控制器进行认证?

TortoiseSVN 有个在 Windows 下设置 Subversion 服务器的完美文档,可以看 http://tortoisesvn.net/docs/
release/TortoiseSVN_en/tsvn-serversetup.html#tsvn-serversetup-apache-5 中的 SSPI
authentication 小节。

配置中比较重要的一部分是这几行:                  SSPIOfferBasic On

如果没有这行,支持 SSPI 的浏览器会提示用户输入凭证,但是不支持 SSPI 的客户端例如 Subversion 就不会提
示。(当前版本的 Neon - Subversion 的 HTTP 库 - 只能处理基本的认证。)因为客户端永远不会被请求凭
证,任何需要认证的操作都会失败。添加这一行告诉 mod_auth_sspi 对客户端使用基本认证,但使用 Windows
域控制器认证凭证。
我不喜欢 “.svn”这样的目录名字,而喜欢 “SVN”或者其他一些目录名,我该如何改变
呢?

如果可能,我们推荐你使用".svn",然而,如果你在 Windows 下使用 ASP.NET,你可能需要按这里的介绍设置
环境变量 SVN_ASP_DOT_NET_HACK。

或者你可以使用一个完全自定义的管理区域名称,我们反对这样做,因为你的工作拷贝可能无法与你的
Subversion 客户端协调工作,然而,如果你喜欢,只需要将 subversion/include/svn_wc.h 的这一行从
#define SVN_WC_ADM_DIR_NAME ".svn"

修改为(例如) #define SVN_WC_ADM_DIR_NAME       "SVN"

然后重新编译客户端。

如何更改一个文件名的大小写?

这个问题在两种情况下会发生。如果你的操作系统使用的文件系统对大小写不敏感,例如 windows 系统,当你在
添加文件的时候,你可能会不小心的添加一个文件名大小写错误的文件。或者,你可能只是想改变版本库中已有
文件的大小写。

如果你是在一个大小写敏感的文件系统上工作,那基本上就不会出现这样的问题。直接将文件改成新的名字。例
如, svn mv file.java File.java

但这样的方式在 windows 这类大小写不敏感的文件系统上是不能正常运作的。在 windows 下,你只能临时地将
文件拷贝到其他地方,然后从 Subversion 中删除该文件,然后重新添加名字大小写正确的文件副本。或者更好
的办法就是对 Subversion 的 URL 执行移动操作。推荐使用操 作 URL 的方法,因为这样可以保持文件的历史日
志,而且能够立即生效。

尽管如此,这两种方式都会导致 windows 下的工作拷贝出现一些问题,因为当试图更新文件名产生冲突的文件的
时候,windows 还是会不知所措。(你可能会得到一条消息如:svn: Failed to add file 'File.java': object of
the same name already exists)。一个解决这个问题的办法就是删除工作拷贝然后重新检出。如果你不想这么
做的话,那么你就必须执行上面提到的两个步骤来更新。

对于每个大小写错误的文件,执行下面的命令将会改变大小写: svn mv
svn://svnserver/path/to/file.java svn://svnserver/path/to/File.java

要更新工作拷贝,你先得转到相关的目录,然后执行: svn update file.java


svn update

第一步的更新会从你的工作拷贝中删除 file.java,第二步更新会添加 File.java,这样就会生成一个正确的
工作拷贝。或者如果你有很多这种问题的文件,你可以按下面的方式来更新工作拷贝: svn update *


svn update

就像你看到的,添加一个大小写错误的文件在文件系统大小写不敏感的操作系统上,是需要一些小技巧来修正
的。所以最好当你第一次添加文件的时候,一次性就添加对了。为了防止类似的问题再发生,你可以创建一个
pre-commit 的钩子脚本,在其中调用文件 check-case-insensitive.pl。这个文件放在 Subversion 的源代码包
里,在 contrib/hook-scripts 目录中
我不能象 CVS 那样使用标签将一个分支的变更合并到主干(trunk),可以吗?

就像下面展示的,你可以不需要记住版本号就将一个分支合并到主线上面。反之亦然(在例子中并没有展示)。

下面这个例子假设在/home/repos 存在一个版本库,你希望从中创建一个名叫 bar 的、包含你即将编辑的文件
foo 的分支。

为了跟踪分支合并的历史,版本库建立了 tags/branch_traces/目录用来保存 tags。 # setup branch
and tags


$ svn copy file:///home/repos/trunk 
           file:///home/repos/branches/bar_branch 
           -m "start of bar branch"
$ svn copy file:///home/repos/branches/bar_branch 
           file:///home/repos/tags/branch_traces/bar_last_merge 
           -m "start"

# checkout branch working copy
$ svn checkout file:///home/repos/branches/bar_branch wc
$ cd wc

# edit foo.txt file and commit
$ echo "some text" >>foo.txt
$ svn commit -m "edited foo"

# switch to trunk and merge changes from branch
$ svn switch file:///home/repos/trunk
$ svn merge file:///home/repos/tags/branch_traces/bar_last_merge 
            file:///home/repos/branches/bar_branch

# Now check the file content of 'foo.txt', it should contain the changes.

# commit the merge
$ svn commit -m "Merge change X from bar_branch."

# finally, update the trace branch to reflect the new state of things
$ svn delete -m "Remove old trace branch in preparation for refresh." 
             file:///home/repos/tags/branch_traces/bar_last_merge
$ svn copy file:///home/repos/branches/bar_branch                     
           file:///home/repos/tags/branch_traces/bar_last_merge       
           -m "Reflect merge of change X."

为什么$Revision$关键字不是我预想的那样?它替换的是文件最后修改的修订版
本,但有时候我希望它能替换文件的当前修订版本。

Subversion 每次都将整个版本库的版本号整个进行自增,所以它不能将关键词替换成你想要的数字 - 它可能不
得不在每次更新或者提交时对工作拷贝中的每个文件进行搜索或者修改。

你想要的信息(你的工作拷贝的版本号)可以通过 svnversion 命令来获取;你可以根据指定的工作拷贝的路径提
供其版本相关的信息(更多细节参考 svnversion --help)。

你可以将其组合到你的构建或发布过程中,以获取需要存放到源代码的信息。例如,在一个基于 GNU make 的构
建环境中,在你的 Makefile 中添加如下的信息: ##
## To use this, in yourfile.c do something like this:
## printf("this program was compiled from SVN revision %sn",SVN_REV);
##

SVNDEF := -D'SVN_REV="$(shell svnversion -n .)"'
CFLAGS := $(SVNDEF) ... continue with your other flags ...

(注意这段代码在非 GNU 版本的 make 中无效,如果你的构建过程需要可移植,请不要使用它。)

或者使用如这些方法: ##


## on every build, record the working copy revision string
##
svn_version.c: FORCE
    echo -n 'const char* svn_version(void) { const char* SVN_Version = "' 
                                       > svn_version.c
    svnversion -n .                   >> svn_version.c
    echo '"; return SVN_Version; }'   >> svn_version.c

##
## Then any executable that links in svn_version.o will be able
## to call the function svn_version() to get a string that
## describes exactly what revision was built.
##

Windows 用户会希望使用 SubWCRev.exe,TortoiseSVN 的下载页面就有;可以用当前工作拷贝的修订版本
替换给定文件中的所有$WCREV$标签。

Subversion 是否有一个功能类似 CVS 的$Log$的关键字呢?

没有。在 CVS 中没有对应的$Log$关键字,如果你希望将日志信息输入某个特定文件,你可以使用'svn log
your-file-name'或'svn log url-to-your-file'。邮件列表中有几个解释$Log$缺点的例子: “当你开
始合并分支之间的变更时,$Log$会是一个完全的梦魇。你一定会在这里得到冲突 -- 因为关键字的本性 -- 很
难简单的自动解决冲突。”

而且: Subversion 的日志信息是可以改变的,可以通过设置 svn:log 修订版本属性修改。所以在任意文件扩
展$Log:$会造成数据的过时,更新操作可能需要访问所有出现$Log:$关键字的文件,即使这些文件没有其他的
变更。

我对此并不在意,我还是期望使用它,你能实现吗?

不能,我们自己没有计划实现它,也不会接受实现这个特性的补丁。如果你希望发布包含某种变更日志的文件,
你可以在你的构建系统中跳出这个限制。

在我的工程里有一个文件,每个人都必须改变它,但是我不希望他们本地的修改被提
交,如何让'svn commit'忽略这个文件?

答案是:不要将文件纳入版本控制,而是将文件的模板纳入版本控制,例如“file.tmpl”。

然后,在初始化的‘svn checkout’之后,让你的用户(或你的构建系统)执行通过普通的操作系统复制将文件修
改为正确的文件名,文件未版本化,所以绝不会提交。并且如果你 希望,你可以将文件加入到父目录的
svn:ignore 属性中,这样它就不会在‘svn status’命令中显示‘?’。
当我通过 svn+ssh 来访问一个版本库的时候,我的密码没有被缓存在
 ~/.subversion/auth/,我应该如何避免每次都要键入密码?

ssh 拥有自己的密码短语和认证缓存模式,它的认证缓存是 Subversion 之外的,需要独立于 Subversion 设置。

OpenSSH 使用 ssh-keygen 创建密钥、通过 ssh-agent 缓存密码短语、使用 ssh-add 将密码短语添加到代
理缓存中。一个简化 ssh-agent 使用的脚本是 keychain。在 Windows 下,PuTTY 是一个流行的 ssh 客户端
选择;将 OpenSSH 密钥导入到 pageant 并缓存密码短语可以看 PuTTYgen。

设置 ssh-agent 已经超出了本文的范围,但是在 Google 中搜索“ssh-agent”可以快速得到答案,或者如果你
没有耐心,可以是看这些:        http://mah.everybody.org/docs/ssh


   http://kimmo.suominen.com/docs/ssh/

 我的 svnserve 二进制程序不在我的用户的默认路径中,他们使用 svn+ssh,我不知
 道怎样修改他们的路径来让他们运行 svnserve。

注意:这里都假设你使用了 OpenSSH。也有一些其他的 ssh 实现,大概它们也实现了这些功能,但是我们不知
道具体的方法。

你已经对修改过各种诸如.bash_profile 的登录文件,但是没有效果!那是因为当 Subversion 客户端调用 ssh 时
会忽略那些文件。但是没有必要修改 PATH;相反,你可以直接在 svnserve 命令中使用 ssh 的完全名,下面是一
个例子:

对于每个需要通过 svn+ssh 访问的用户,生成一个新的 Subversion 使用的 ssh 公钥对—不是用来登陆的。让他
们给密钥对不同的名称,例如~/.ssh/id_dsa.subversion。将密钥的公共部分添加到服务器主机的
~/.ssh/authorized_keys 中,在开始部分包含 ssh-rsa 或 ssh-dss 以及一些幻数的行中,如下:

                                  之前
ssh-dss AAAAB3Nblahblahblahblah
                                  之后
command="/opt/subversion/bin/svnserve -t" ssh-dss
AAAAB3Nblahblahblahblah
很明显,需要将/opt/subversion/bin/svnserve 替换为你主机上的相应值。你也会希望在命令行指明
Subversion 版本库的完全路径(通过-r 选项),节省用户使用时的输入。

command=魔法可以让远程主机的 sshd 调用 svnserve,即使你的用户尝试运行其他命令,更多细节可以看
sshd(8)的 man 页(AUTHORIZED_KEYS FILE FORMAT 部分)。

现在当你的用户运行 Subversion 客户端时,请确定他们有一个 SVN_SSH 环境变量是“指向”他们密钥对的私有
部分,通过下面的方法(Bourne Again shell): SVN_SSH="ssh -i
$HOME/.ssh/id_dsa.subversion"


export SVN_SSH

这个主题的详细讨论可以看这个文件。
我希望允许通过 svn+ssh://来访问版本库,但我很忧虑。我讨厌为每个用户分配一
个登录帐号的方法,那样我会为他们是否允许访问我的机器感到担心。

可以看对其他问题的回答中关于修改~/.ssh/authorized_keys 的部分;先不管将 svnserve 设置到路径的问
题。

我怎么才能为版本库的所有文件设置一个的属性?另外,我该如何确保每个添加到版
本库里的新文件都有这些属性?

Subversion 缺省情况下不会修改文件的内容;你可以设置 svn:eol-style 或 svn:keywords 属性实现这个功
能。这让 Subversion 比 CVS 的缺省行为模式更加安全,但是安全也带来了不便。

第一个问题的答案是:设置所有已经进入版本库的文件,将会有点困难。你所要做的是在每个文件(工作拷贝文
件)上执行 svn propset,然后执行 svn commit,通过脚本应该可以帮助你做这件事。

但是对以后的文件呢?很不幸,没有在服务端自动设置提交文件属性的机制。这意味着你需要让你的用户记住在
每个 svn add 的文件上添加属性,幸运的是,有一个客户端的工具可以帮助我们做这件事,可以阅读本书的
auto-props 特性。你需要保证所有的用户配置了合适的自动化属性。

你可以写一个 pre-commit 钩子脚本来拒绝忘记在新文件添加属性的提交(例子可以看
http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/check-mime-type.pl)。然而这个方法有
点过激了,例如某人忘记了设置 svn:eol-style,那么在其他系统上用户很快就会注意到,一旦发现,可以很简单
的修正:只要设置正确的值,并提交。

注意:许多用户期望得到服务器“自动广播”运行中设置的特性,例如自动化属性设置。对此已经有了一个特性请
求(issue 1974),然而这个特性还存在争议,还没有去实现。

我如何处理编辑器路径中的空白?另外,如何定义编辑器的命令行选项?

Subversion 命令行客户端会调用通过环境变量 SVN_EDITOR. 定义的编辑器,这个环境变量以及要编辑日志的
临时文件会直接传递给操作系统。

因为是要将 SVN_EDITOR 的字符串传递给系统命令行,所以如果你不加引号,编辑器名称中的空格或路径中的
空格会造成错误。

例如,在 Windows 下,如果你的编辑器在 C:Program FilesPosix Toolsbinvi,你需要这样设置环境
变量:    set SVN_EDITOR="C:Program FilesPosix Toolsbinvi"

请注意没有必要在 windows 下回避引号,因为他们不是 set 命令语法的一部分。

而在 UNIX 系统中,你需要遵从你 shell 的特定方法来设定变量,例如在 bash shell 中,应该这样:
SVN_EDITOR='"/usr/local/more editors/bin/xemacs"'


   export SVN_EDITOR

如果调用编辑器需要命令行选项,只要在 SVN_EDITOR 环境变量的编辑器名称后面输入选项,就像你平时调用
它时那样。例如,如果你的编辑器需要-nx -r 选项,可以按照下面的方式设置:

在 Windows 下:     set SVN_EDITOR="C:Program FilesPosix Toolsbinvi" -nx -r

在 UNIX/bash 中:     SVN_EDITOR='"/usr/local/more editors/bin/xemacs" -nx -r'
export SVN_EDITOR

请注意 SVN_EDITOR 是 Subversion 特定的设置编辑器的环境变量,Subversion 也支持使用更普遍的
EDITOR 环境变量,但是如果你希望一些对于 Subversion 特殊的行为方式,最好还是使用 SVN_EDITOR 变
量。

 如何确定版本库正在使用的 Berkeley DB 的版本?

如果它是一个活动的版本库,那么对于这个问题最简单的答案是“你安装的 Berkeley DB 的版本”。但是,如果它
是备份的或其它未知源得到的版本库,你对其的 Berkeley DB 版本一无所知,下面是你确定它的方法:

运行命令查看版本库中的高位计数文件 db/log.*中位移 12 到 16(10 进制)的两个 4 字节的整数。这里是 GNU
od 的例子:“od -j12 -N8 -tx4 log.<number>”。而这里是 Mac OS X hexdump 的例子:“hexdump -s12
-n8 -x log.<number>”。第一个整数一定是幻数 0x00040988,用来注明这是 Berkeley DB 日志文件,第二
个数字是日志格式版本 - 可以使用下面的表格和 Berkeley DB 的版本匹配:

                Berkeley DB 版
 日志格式版本
                     本
5 (0x00000005) 4.0
7 (0x00000007) 4.1
8 (0x00000008) 4.2
10
                4.3
(0x0000000a)
11
                4.4
(0x0000000b)
12 (0x0000000c) 4.5
13
                4.6
(0x0000000d)

 我在版本库中管理了一个网站,如何才能实现每次提交之后站点自动更新?

这个早已经解决,可以通过为版本库添加 post-commit 钩子脚本简单实现,可以读一下手册第 5 章关于钩子脚本
的内容,基本的思想是让“活动站点”变成一个普通的工作拷贝,让 post-commit 在工作拷贝中执行‘svn
update’。

在实践中,有许多地方需要小心。执行提交的服务器程序(svnserve 或 apache)也是执行 post-commit 钩子
脚本的程序,这意味着 程序必须有正确的更新工作拷贝的访问许可。换句话说,运行 svnserve 或 apache 的用
户应该拥有工作拷贝 -- 或至少工作拷贝设置了合适的访问许可。

如果服务器需要更新它并不拥有的工作拷贝(例如,用户 joe 的~/public_html/区域),一个技巧是创建一个
+s 的二进制程序运行更新,因为 Unix 不允许为脚本运行+s,编译一个小的 C 程序: #include <stddef.h>


#include <stdlib.h>
#include <unistd.h>
int main(void)
{
  execl("/usr/local/bin/svn", "svn", "update", "/home/joe/public_html/",
        (const char *) NULL);
  return(EXIT_FAILURE);
}
... 然后对二进制程序 chmod +s,并确认它确实被用户‘joe’所有,然后在 post-commit 钩子中,添加一行运行
二进程程序。

如果在让钩子运行时发生了问题,可以看“为什么我的钩子脚本都不能正常工作?”。

另外,你可能希望防止 apache 把工作拷贝中的.svn/目录暴露出去,在你的 httpd.conf 添加下面的内容: #
Disallow browsing of Subversion working copy administrative dirs.


<DirectoryMatch "^/.*/.svn/">
    Order deny,allow
    Deny from all
</DirectoryMatch>

我如何检出一个单独的文件?

Subversion 不支持检出单个文件,它只支持检出目录结构。

然而,你可以使用‘svn export’来导出单个文件,这会获得文件的内容,只是不会创建版本化的工作拷贝。

如何在工作拷贝执行完添加、删除、拷贝和重命名操作之后检测这些操作?

你不需要检测,你也最好不要尝试去做这样的检测。

工作拷贝的基本设计有两个原则:(1) 你可以任意编辑文件,然后(2)使用 Subversion 客户端执行任何树目录的
改动(增加、删除、移动、拷贝)。如果这两个原则能够很好的遵守,那么客 户端就可以顺利的维护工作拷贝。
如果重命名或者其他改动是在 Subversion 之外进行的,那么 UI 就会被破坏,工作拷贝也可能发生问题。客户端
不能猜 测究竟发生了什么事。

人们有时候会遇到这样的错误,因为他们想要把版本控制变得透明化。他们诱使用户使用一份工作拷贝,然后在
稍候运行一个脚本,这个脚本会猜测用户做了 什么样的操作,然后执行相应的客户端命令。不幸的是,这样的方
式只能在短期内正常工作。‘svn status’会显示出缺失条目或者未被纳入版本控制的条目,这些条目在脚本运行的
时候会自动的被‘svn rm’或者‘svn add’。但如果发生了文件移动或者拷贝,那么你就不那么幸运了。即使脚本有
非常可靠的方法来检测这些动作,但‘svn mv’和‘svn cp’不能在这些操作已经完成的情况下运行。

总的来说,工作拷贝必须整个放置在 Subversion 的版本控制之下,Subversion 本来就不是设计成对用户透明
的。如果你想要获得这种透 明性,那么你应该建立一个 apache 服务器,然后本书附录 C 使用
的“SVNAutoversioning”特性。这将允许用户将版本库挂载成一个网络磁 盘的形式,任何对这个磁盘的修改,
都会自动提交到远程服务器上。

在 Windows 上如何将 svnserve 当作服务来运行?

对于 1.4.0 及以后的版本,你可以查看这里。

对于 1.4.0 以前的版本,svnserve 二进制本身并不可以被安装成一个 windows 服务,但有很多“service
wrappers”可以完成一样的工作。例如:

  •   SVNService Magnus Norddahl 写的一个免费的工具
  •   SrvAny 微软出的免费的工具

在 TortoiseSVN 手册还有一点内容关于怎么将 svnserve 安装成服务的形式。
如何转换我的版本库,从 BDB 到 FSFS,或者从 FSFS 到 BDB?

有三步:

  1. 使用 dump/load 将旧格式转到新格式。
  2. 拷贝钩子脚本。
  3. 拷贝配置文件。

假设你在/svn/myrepos 目录中放置了一个版本库,使用的是 BDB,你想要将其转换成 FSFS:

  1. 关闭你的服务器,这样在这个过程中数据不会发生变化。
  2. 创建一个使用 fsfs 的新的版本库(这在 1.2 版本依赖就是默认的行为)。例如,svnadmin create /svn/
     myreposfsfs --fs-type fsfs。
  3. 将/svn/myrepos 的转储输出通过管道重定向到/svn/myreposfsfs 的加载输入上,例如,svnadmin
     dump /svn/myrepos -q | svnadmin load /svn/myreposfsfs。Windows 用户应该转储到一个文件
     中,并且从那个文件中加载,需要分两步完成。
  4. 复制在/svn/myrepos/hooks 中仍使用的钩子脚本到/svn/myreposfsfs/hooks 中。不要所有东西都拷
     贝,有些模板是由 Subversion 自动生成的,可能会不一样。
  5. 比较/svn/myreposfsfs/hooks 目录中 svnadmin create 命令生成的脚本模板
     和/svn/myrepos/hooks 中的有什么不一样,将这些不同按需合并到你正在使用的钩子脚本中。
  6. 从/svn/myrepos/conf 复制配置文件到/svn/myreposfsfs/conf 中(如果有密码文件的话,也不要忘
     了)。或者你想要将配置文件中所做的修改合并到新的默认配置文件中。
  7. 重命名/svn/myrepos 为/svn/myreposbdb,还有/svn/myreposfsfs 重命名为/svn/myrepos,这样
     可以确保文件权限和 BDB 版本的一样。
  8. 重启服务器。

一旦一切工作正常后,删除旧的版本库即可。

如果要反过来操作,即从 FSFS 移植到 BDB,只需要改变 svnadmin create 命令,将其指定为 BDB 即可。

版本库如何处理二进制文件?

当你第一次添加或者导入文件到 Subversion 中时,Subversion 会检测该文件是否是二进制文件。目
前,Subversion 的策略是 只检测文件的前 1024 个字节;如果每个字节都是 0,或者超过 15%都是非 ASCII 码
可打印字符的话,那么 Subversion 就认定该文件是二进制文 件。这种启发式方法将来可能会改进。

如果 Subversion 认定文件是二进制文件,那么这个文件就会自动添加 svn:mime-type 属性,并设置
为“application/octet-stream”。(你随时可以使用 auto-props 特性来重写这样的行为,或者使用 svn
propset 手动设置属性。)

Subversion 对以下的文件做普通文本处理:

  •   没有设置 svn:mime-type 属性的文件
  •   文件的 svn:mime-type 属性值以“text/”开头
  •   文件的 svn:mime-type 属性值等于“image/x-xbitmap”
  •   文件的 svn:mime-type 属性值等于“image/x-xpixmap”

所有其他文件都将被视为二进制文件处理,这意味着 Subversion:

  •   不会尝试在 svn update 或者 svn merge 操作时将远程修改合并到本地中
  •   在 svn diff 中不会显示出不同
  •   在 svn blame 不会显示出每一行的贡献者
在其他方面,Subversion 将二进制文件和其他文本文件一样对待,例如,如果你设置了 svn:keywords 或者
svn:eol-style 属性,Subversion 会在二进制文件中执行关键词替换或者行转换。

需要注意,不管是不是二进制文件,都不会影响版本库中用来存储文件变更的空间大小,也不会影响客户端和服
务端之间的通讯量。出于存储和传输考 虑,Subversion 使用的是对二进制文件和普通文本文件一致处理的
diffing 方法;这和‘svn diff’使用的 diffing 方法完全不相 关。

如何让 svn diff 仅显示被改变的文件的名字,而不是连内容也显示出来?

svn diff 没有一个选项可以做到这一点,但是

   •    如果你只是对修订版本号 10 和之前的版本之间的变动感兴趣,那么使用 svn log -vq -r10 完全可
        以实现你的目的;
   •    否则,如果你是在使用 Unix 系统的话,下面这个方法对于任意范围的版本号都起作用:                    svn log
        -vq -r123:456 | egrep '^ {3}[ADMR] ' | cut -c6- | sort | uniq

1.4 版本的 svn diff 命令有一个“--summarize”的参数。

我如何使用通配符(wildcards)或者点号来一次移动多个文件?

你或许是想做这样一些事情 svn mv svn://server/trunk/stuff/* svn://server/trunk/some-
other-dir

但是却失败了 svn: Path 'svn://server/trunk/stuff/*' does not exist in revision 123

... 或者还有其他一些看起来不可理解的错误信息。

简而言之,很不幸:Subversion 没有内置这样的方法来进行这样一种操作;许多其他的命令,例如 mv,不会接
受任意数目的参数...在任何情况下,Subversion 都不会扩展如 shell 所支持的“*”号通配符。

如果你刚好有一个工作拷贝包含了和目标目录一摸一样的源文件,那么你可以使用你的 shell 中的通配符特性来
完成移动文件的目的,例如(在 bash 下): for i in stuff/*; do svn mv $i some-other-dir;
done


  svn ci -m "moved all the stuff into some other dir"

在任何情况下,你都可以将源文件的名字拼成一个列表,然后使用“svn mv”命令对列表中的每一项都执行同样的
指令,就像下面所做的一样:     s=svn://server/trunk/stuff/


         svn ls "$s" | 
         while read f
            do svn mv "$s/$f" svn://server/trunk/some-other-dir -m "Moved just one
file"
         done

但是需要注意的是,这样会造成每个文件都执行一次提交动作,这和上面的方法(使用工作拷贝)不同,上面的
方法总共就会执行一次提交动作。

有一个程序叫“svnmucc”或者“mucc”可以解决你的这个问题,不过它依赖于你的 Subversion 版本号,它的源
代码已经发布在 Subversion 中了(对于 Subversion 1.4 以及更早的版本,这个工具的源文件放置在/contrib/
client-side/mucc/mucc.c,对于 1.5 及之后的版本,则在/contrib/client-side/svnmucc/svnmucc.c 可以找
到)。
注意:随着 1.5 版本的正式发布,Subversion 事实上允许你一次性同时“cp”和“mv”多个文件。

我如何用 Subversion 维护一个由第三方不断修正版本的软件呢?(一个"供方分
支")?

人们通常希望使用 Subversion 去跟踪他们的变化的第三方代码,甚至从第三的代码进行升级,换句话说,他们
想维护他们自己的一个分支,与此同时仍然希望从上游的代码并入新的发布。这通常被叫做供方分支(这个术语
早于 Subversion),Subversion 维护这种分支的技术可以看这个描述。

如果供方代码是远程的主机上的 Subversion 版本库,你可以使用 Piston 来管理你的供方代码拷贝。

最后,如果使用 svn_load_dirs.pl 花太多时间的话,或者你正在寻找一个偷懒的方案,则可以参考 Jon
Stevens 的渐进介绍如何使用 Subversion 供方分支。这种解决方案在你拷贝新的代码去覆盖旧代码的时候并不
能利用 Subversion 后端的节省空间特性换;在这种解决方案中,每一份导入的供方代码都会是一个新的拷贝,
相同的文件不会节省存储空间。


疑难解答:

我的版本库经常看起来卡住了,一直报一个需要重新恢复(DB_RUNRECOVERY)的
错误,怎么会导致这个问题?

版本库使用的 Berkeley DB 数据库很容易受到破坏。如果进程退出时没有正常关闭数据库,那么数据库就处在非
正常状态中。常见的原因可能是:

  •   进程遇到访问权限问题而退出时
  •   进程崩溃或段错误
  •   进程被强制杀死
  •   磁盘空间用尽

多数情况下,你可以执行"svnadmin recover",这个命令可以将版本库回退到上一个正常状态,详细解释请见
bdb-recovery。注意,当频繁的 checkout 和 update 且磁盘空间用尽的时候,可能导致版本库处于无法恢复的
状态(所以请多做备份)。

进程崩溃,被杀死以及磁盘空间用尽都是极端情况。访问权限问题可能是更常见的原因:当一个进程访问版本库
且改变了版本库的所有者或访问权限,那么另一个访问这个版本库的进程可能被阻塞在访问权限上。

避免这种情况出现的最好办法是正确设置你的版本库的所有者和权限。查看更多信息。

每次我想访问我的版本库,进程就会挂起。我的版本库坏掉了吗?

你的版本库没有坏掉,数据也没有丢失。当你的进程直接访问版本库(mod_dav_svn、svnlook、svnadmin,
或通过 ‘file://’)的时候,进程将直接通过 Berkeley DB 来访问版本库。Berkekey DB 包含日志系统,也就是
说所有的操作在执行前都被记录在日志中。当你的进程崩溃(Control-C,或段错误),遗留下文件锁,它记录了
所有未完成操 作的信息。此时所有试图访问数据库的进程将因为要访问文件锁而被挂起。要想解除文件锁,你可
以调用 Berkeley DB 来完成所有未完成的操作或者回退到前一个正常状态。

警告:当一个进程正在访问版本库,而你又试图恢复版本库的时候,版本库可能会严重损坏。

在你恢复数据库之前,请确保没有其他进程在访问版本库(关闭 Apache, 去掉'svn'的执行权限) 。确认你是以数
据库所有者及管理员的用户进行操作的,而不是 root 用户。否则数据库将只能被 root 用户访问,而其他用户
(你自己或 Apache)将无 法对数据库进行操作。同时,还要确保 umask 被正确设置,否则其他隶属与可以访
问该数据库的组的用户可能无法对数据库进行操作。
执行:     svnadmin recover /path/to/repos

当命令执行完毕, 检查版本库 db 目录的访问权限

有时"svnadmin recover"会失败,错误信息如下:           Repository lock acquired.


 Please wait; recovering the repository may take some time...
 svnadmin: DB_RUNRECOVERY: Fatal error, run database recovery
 svnadmin: bdb: Recovery function for LSN 175 7066018 failed on backward pass
 svnadmin: bdb: PANIC: No such file or directory
 svnadmin: bdb: PANIC: fatal region error detected; run recovery

或者:    Repository lock acquired.


 Please wait; recovering the repository may take some time...
 svn: DB_RUNRECOVERY: Fatal error, run database recovery
 svn: bdb: DB_ENV->log_flush: LSN of 115/802071 past current end-of-log
 of 115/731460
 svn: bdb: Database environment corrupt; the wrong log files may have
 been removed or incompatible database files imported from another
 environment
 [...]
 svn: bdb: changes: unable to flush page: 0
 svn: bdb: txn_checkpoint: failed to flush the buffer cache Invalid argument
 svn: bdb: PANIC: Invalid argument
 svn: bdb: PANIC: fatal region error detected; run recovery
 svn: bdb: PANIC: fatal region error detected; run recovery
 [...]

这种情况下可以试试 Berkeley DB 的工具 db_recover (参见 db_recover 文档).这个命令通常在 Berkeley
DB 安装目录的子目录"bin/"中, 例如你从源代码安装的 Berkeley DB,命令可能是 /usr/local/BerkeleyDB.4.2/
bin/db_recover;或在某些系统中预安装的 Berkeley DB,可能是 /usr/bin/db_recover.如果你的系统中安装
了多个版本的 Berkeley DB,请确保使用匹配版本库的 Berkeley DB 版本

执行 db_recover,附带参数"-c" ("灾难恢复").你还可以附带 "-v"来看到执行的详细信息, "-h"指定被
恢复的数据库。例如:       db_recover -c -v -h /path/to/repos/db

用版本库的拥有者的帐号执行这个命令,同时,请绝对确保没有其他进程在 访问版本库。(例如,关闭
svnserve 或)。

我的版本库一直报告错误"Cannot allocate memory",我该怎么办?

如果你通过 http://来访问版本库,"Cannot allocate memory"应该出现在 httpd 服务器的日志中,像下
面这样: [Wed Apr 07 04:26:10 2004] [error] [client 212.151.130.227] (20014)


Error string not specified yet: Berkeley DB error while opening
'strings' table for filesystem /usr/local/svn/repositories/svn/db:
Cannot allocate memory
[Wed Apr 07 04:26:10 2004] [error] [client 212.151.130.227]
Could not fetch resource information. [500, #0]
[Wed Apr 07 04:26:10 2004] [error] [client 212.151.130.227]
Could not open the requested SVN filesystem [500, #160029]
[Wed Apr 07 04:26:10 2004] [error] [client 212.151.130.227] (17)
File exists: Could not open the requested SVN filesystem [500, #160029]

这通常表示 Berkeley DB 版本库用光了所有数据库锁(FSFS 版本库不会出现这种情况)。通常的运行过程中不
应该出现这种情况,如果确实出现了,解决办法是用本文中描述的方法来恢复数据库。如果这种情况时常发生,
你很可能应该提高 db/DB_CONFIG 文件中锁设置(set_lk_max_locks、set_lk_max_lockers 和
set_lk_max_objects)的默认值。改变已存在的版本库的 DB_CONFIG 配置后,记得恢复数据库。

每当我试图运行一个 svn 命令时,都会提示我的工作拷贝已经被锁定了,是我的工作
拷贝坏掉了吗?

你的工作拷贝没有坏掉,数据也没有丢失。Subversion 的工作拷贝是一个日志系统,所有的操作在执行之前都
被记录在日志中。如果 svc 客户端程序被 强制中止(段错误或杀进程,不包括 Control-C),会有多个文件锁
遗留下来,记录了未完成的操作。('svn status'命令会在被锁定的目录后显示'L'。)其他试图访问工作拷
贝的进程看到这些锁后会返回操作失败。想解锁你的工作拷贝,需要让 svn 客户端完 成未完的操作。执行:
svn cleanup working-copy

我试图去提交,但是 Subversion 说我的工作拷贝是过时的?

三种情况下会出现这个问题

提交失败导致了你的工作拷贝被破环。

在你提交时,新版本被添加到服务器上,然后你的客户端执行提交后的管理任务(包括刷新本地拷贝)。在第二
个操作之前,你的提交处在一个“过期”的状态之中。导致这种情况发生的原因有,(极少数情况下)数据库一端
出现了问题,(大多数情况下)网络在错误的时间中断了。

这 时,很可能你的提交已经成功了。你可以执行"svn log -rHEAD"来查看提交是否真的成功了。如果成功了,
执行“svn revert”,回退本地修改,然后执行“svn update”来取回你已经提交的修改。(注意,“svn
update”能更新你的本地拷贝,而 revert 不能。)
版本混杂。

提交的时候,在客户端的工作拷贝中,只有此次提交涉及的节点会被更新,而不是所有节点。这意味着, 你最后
一次提交决定你的工作拷贝中了文件和目录的版本号,他们可能不是同一版本。对于像修改目录属性等特定操
作,如果版本库中有更新的版本,你的提交会被 拒绝,以防止数据丢失。详细请见版本混杂的局限在使用
Subversion 做版本控制中。

执行'svn update'可以解决这个问题。
你的版本可能确实是过时的 — 即在你提交的时候,有人基于你的上一次改动又作了更新。执行'svn update'来解
决这个问题。

我为项目贡献了一个补丁,而这个补丁添加了一个新文件,现在 svn update 不能工
作了。

如果要往补丁里加入新文件,你可能得使用 svn add 命令,这样 svn diff 命令才会将新文件包含在补丁里面。如
果你的补丁已经提交到代码库里头了,然后你运行 svn update,这个时候你可能会收到错误提示:“svn:
Failed to add file ‘my.new.file’。object of the same name already exists”(不能增加“my.new.file”,
同名文件已经存在)。

之所以会产生这个错误是因为你的工作拷贝中已经有这个文件了。解决这个问题的步骤如下:

   1. 运行 svn revert 命令,把原先标记为添加的修改撤销掉。
   2. 删除文件或者将其移动到工作拷贝外的其他位置。
3. 现在你应该可以运行 svn update 命令了。

你可能需要把版本库中的新文件和你的本地的文件做一下比较。

我编译了 Subversion 的发行版,当我试图 check out 的时候,我得到一个错
误"Unrecognized URL scheme."这时怎么回事呢?

Subversion 使用了插件系统来访问版本库。现在支持三个插件:ra_local 支持访问本地版本库,ra_dav 支持通
过 WebDAV 访问 版本库,ra_svn 支持通过 svnserver 服务器访问远程或本地的版本库。当你执行 Subversion
的操作时,会根据 URL scheme 来决定加载哪一个插件。以`file://'开头的 URL 会加载 ra_local,`http://'开
头的 URL 会加载 ra_dav。

你看到的错误是说无法找到正确的插件。发生这个问题,通常是因为你将 Subversion 的库文件编译成动态库
后,却没有执行'make install'。或者虽然你执行了'make install',但是操作系统还是找不到 Subversion 的动
态库所在的路径。在 Linux 系统中,你可以把相应的路径加入到/etc /ld.so.conf 中,然后运行 ldconfig。如果
你不想这么作,又或者你没有 root 权限,你可以在 LD_LIBRARY_PATH 中指定相应 的路径。

当我查找或打开一个版本库时出现错误,但是我知道我版本库 URL 是正确的,哪里出
错了?

参考这个 FAQ 条目。

当我运行`configure'命令时,出现一些错误 subs-1.sed line 38: Unterminated
`s' command。 这是怎么回事?

可能你系统里的/usr/local/bin/apr-config 和/usr/local/bin/apu-config 太旧了。删了它们,更新 apr/和 apr-
util/,使其和你编译的版本保持一致,再重新编译。

我在 Windows 下用 MSVC++6.0 构建 Subversion 时候有些麻烦,我该怎么办?

可能你需要最新版本的 platform SDK,VC++ 6.0 带的 SDK 太旧了。

我如何在 file:格式的 URL 中指定 Windows 盘符?

像这样: svn import file:///d:/some/path/to/repos/on/d/drive

更多细节请见 Subversion 书中的版本库 URL。

VS.NET/ASP.NET 似乎不能处理".svn"目录名。我该怎么办?

VS.Net 有一个 ASP.Net 子系统,它使用 WebDAV 来通过 IIS 来远程发布。这个子系统剔除了所有以"."开头的
目录。在你试图远程发布 你的工作目录的时候,".svn"将导致问题。错误信息类似"unable to read project
information"。

要想绕过这个问题,设置环境变量 SVN_ASP_DOT_NET_HACK 为任意值 — 这将告诉 Windows clients 在你
的工作拷贝中使用"_svn"作为目录名。参见 Subversion 1.3 发布说明的相关章节来取得更多信息,参见这个问
题来用其他方法配置管理目录名。

我在通过网络对 Subersion 版本库进行写操作的时候有些麻烦。

例如,有用户反映,通过本地协议访问的,导入功能正常工作:                     $ mkdir test
$ touch test/testfile
  $ svn import test file:///var/svn/test -m "Initial import"
  Adding         test/testfile
  Transmitting file data .
  Committed revision 1. 但如果从远程访问的话就出错了:             $ svn import
http://svn.sabi.net/test testfile -m "import"
  nicholas's password: xxxxxxx

 svn_error: #21110 : <Activity not found>

 The specified activity does not exist.

我们曾经遇到过这样的问题,当 httpd 进程对 REPOS/dav/目录没有可写权限的时候会发生。你需要检查一下相
关的权限问题,确保 Apache 能够往 dav/目录中写入东西。(当然还有 db/目录)。

在 Windows XP 下,Subversion 服务器有时候会发布一些错误数据,真的是这样
吗?

你需要安装 Windows XP 的 SP1 补丁。你可以在下面这里找到所有相关的信息:

  •   http://support.microsoft.com/default.aspx?scid=kb;EN-US;q317949

在 Subversion 服务器和客户端之间进行交互时,跟踪网络的最好方法是什么?

可以参考 hacking.html#net-trace。

为什么 svn revert 要求有一个明确的目标?为什么它默认不是递归执行的呢?这与所
有其他的子命令都不同。

简而言之,这是为你好。

Subversion 对保护你的数据非常重视,不只是你已经版本化的数据。你对已经版本控制的文件所做的修改,或者
你即将添加到版本库中的文件,都必须小心对待。

使用 svn revert 命令需要非常明确地指定目标—即使目标是‘.’—就是其中一个方面。这个要求(同样对于--
recursive (-R)标记,如果你真的需要递归执行某个操作,你也要这样做)是为了让你清楚的知道你要做的事
情,因为一旦你执行了撤销工作拷贝修改的命令,所有本地的修改都会永远消失。

当我启动 Apache 时,mod_dav_svn 报告"bad database version",它发现的
是 db-3.X,而不是 db-4.X。

你的 apr-util 链接的是 DB-3,而 svn 链接的是 DB-4。不幸的是,DB 符号并不是不相同的。当 mod_dav_svn
被加载入 Apace 的进程空间的时候,他会使用 apr-util 的 DB-3 库来解析符号。

解决办法就是确保 apr-util 是在 DB-4 下编译的。你可以在编译的时候指定特定的开关为 apr-util 的配置或者
apache 的配置:“--with-dbm=db4 --with-berkeley-db=/the/db/prefix”。

在 Red Hat 9 中,我得到一个"Function not implemented"错误,一切都停止工
作。我该如何修正它呢?

这确实不是 Subversion 的问题,但经常会影响 Subversion 用户。
随 Red Hat 9 还有 Fedora 发行的 Berkeley DB 库依赖于对 NPTL 的内核支持(本地 Posix 线程库)。

Red Hat 提供的内核对这方面有内置的支持,但如果你是自己编译的内核,那么你可能不会有 NPTL 的支持。如
果是这个原因的话,那么你可能会看到如下的错误: svn: Berkeley DB error


svn: Berkeley DB error while creating environment for filesystem tester/db:
Function not implemented

这个问题可以按照下面的方法解决:

  •   根据你使用的内核重新编译 Berkeley DB。
  •   使用 Red Hat 9 内核。
  •   使用 NPTL 内核补丁。
  •   使用内置了 NPTL 支持的比较新的内核版本(2.5.x)。
  •   检查 LD_ASSUME_KERNEL 环境变量是否已经设置为了 2.2.5,如果是的话,在重新启动
      Subversion(Apache)之前删除此环境变量。(通常只有当你在 Red Hat 9 上面运行 Wine 或者
      Winex 才需要设置这个环境变量)

要使用 NPTL 版本的 Berkeley DB,你还需要使用支持 NPTL 的 glibc 库,很可能是 i686 版本。参考
http://svn.haxx.se/users/archive-2004-03/0488.shtml。

为什么文件通过 Apache(ra_dav)被提交和导入时,SVN 的日志说 “(no
author)”?

如果你在 Apache 上开启了匿名用户的写权限的时候,Apache 服务器就不会向 svn 客户端询问用户名,而是直
接不经过验证就允许执行写操作。因为 Subversion 不知道谁做了这些操作,日志中这些操作信息就变成下面这
样了: $ svn log


------------------------------------------------------------------------
rev 24: (no author) | 2003-07-29 19:28:35 +0200 (Tue, 29 Jul 2003)

关于如何配置 Apache 的访问权限,参考 Subversion 书籍("Networking a Repository")。

我在 Windows 平台上偶尔会得到一个"Access Denied"错误,它的发生好像没有什
么规律,为什么呢?

这可能是由于一些监听文件系统变化的 windows 服务(如杀毒软件,索引服务,COM+事件通知服务)。这不属
于 Subversion 的 Bug,所以我们很难修正这个问题。关于这种情况的调查说明可以在这里找到。在 7598 版本
中,对这个问题做了改进,对于大多数人来说,应该会降低这种情况出现的几率。如果你使用的是较早的版本,
请更新到最新的发行版。

在 FreeBSD 上,某些操作(尤其是 svnadmin create)有时候会被挂起。为什么?

这通常是由于系统中某些资源不足的缘故造成的。你很可能需要配置一下系统,使其能够从源那里获取足够的资
源,如硬盘还有网络中断。查阅你的系统说明手册,找到 random(4)还有 rndcontrol(8)这几节,看如何修改。
我可以从一个 WEB 浏览器上查看我的版本库,但是在执行'svn checkout' 时发生一
个错误:"301 Moved Permanently"。那个地方出错了?

这意味着你的 httpd.conf 配置有问题,通常情况下,当你设置的 Subversion 虚拟目录同时存在两种寻址方式的
时候会出现这样的错误。

例如,当你将版本库放到/www/foo 目录下,但是你又同时设置了你的版本库的根目录为/www,那么你就麻烦
了。当有人请求 一个/www/foo/bar 文件的时候,apache 根本不会知道,对方真正想要寻找的文件,是在根目
录里下的/foo/bar,还是通过调用 mod_dav_svn 模块从/www/foo 版本库中去把/bar 文件给取回来,通常
Apache 的处理行为是采取前者的方式,因此就会出现“永久转移 ”这样的错误了。

解决这个问题的办法就是确认你的版本库路径不会有重叠,或者存在其他网络共享可访问的路径里面。

出现这个问题还有一个可能的原因,就是在网站根目录存在一个和版本库的 URL 同名的文件(文件夹)。例如,
假设你的 WEB 服务器的根目录设置在 /var/www,你的 Subversion 版本库被放置在/home/svn/repo 目录
下,然后你在 Apache 下将该版本库的 URL 配置成 http://localhost/myrepo。如果你这时又在/var/www 下
创建了一个 myrepo 的目录,那么同样会产生 301 的错误。

为什么 HTTP 摘要认证(HTTP Digest auth)不能正常工作?

这个问题很可能是因为 Apache 服务器的一个已知的 bug(存在于 2.0.48 或者更早期的版本),你可以在
http://nagoya.apache.org/bugzilla/show_bug.cgi?id=25040 找到相应的补丁。你也可以在
http://subversion.tigris.org/issues/show_bug.cgi?id=1608 上看有没有和你说的情况类似的已反馈的
bug。

我在 AIX 上面编译 xls 的时候出现编译错误,为什么呢?

在环境变量 CFLAGS 中加入-qlanglvl=extended 作为配置参数,这会使到编译 xls 的时候更加灵活,这样应该
不会再出现编译错误了。更详细的信息请参阅 http://svn.haxx.se/dev/archive-2004-01/0922.shtml 及相
关的文章。

我使用非递归的方式(使用 -N 参数)检出一个目录后,现在我想让某些特定的子目
录再 “出现 ”,但 svn up subdir 命令不能正常使用。

参考 issue 695. 当前的 svn checkout -N 命令的实现非常糟糕。它会造成工作拷贝某些条目缺失,但它本身又
没有意识到已经出现了不完整性的问题。很显然,很多的 CVS 用户已经对这种使用方式习以为常了,但是
Subversion 的用户还并不习惯。目前还没有好的办法解决这个问题,只能让你自己改变操作的流程:先试着检出
单独的子目录,然后再手动嵌入到你的工作拷贝中。

我试着在 win32 平台的 Apache 上使用 mod_dav_svn 模块,但是却提示我模块未
找到的错误,但是 mod_dav_svn.so 这个文件明明就放在Apachemodules 目
录中。

这个错误信息在这里有点误导人。通常这样的错误是因为 Apache 无法正确加载 mod_dav_svn.so 模块所依赖
的模块。如果当前 Apache 是以服务的形式运行的,那么它的 path 环境变量和普通用户的并不相同。请确认
libdb4*.dll、intl3_svn.dll、 libeay32.dll 还有 ssleay32.dll 都可以在Apachebin 或者Apachemodules
目录中找到。如果没有找到,你可以从 Subversion 的安装目录下拷贝一份。

如果这样还解决不了问题的话,那么你可以使用类似 Dependency Walker 这样的工具来查看
mod_dav_svn.so 库的依赖性,看是否还有尚未解决的依赖性问题存在。
为什么我的钩子脚本都不能正常工作?

这些钩子脚本应该会触发外部程序的,但是这个触发过程似乎并没有执行。

当 Subversion 调用一个钩子脚本时,它会将所有环境变量都清除干净,包括 unix 下的$Path 和 windows 下
的%Path%变量,因此,如果你的脚本要访问外部程序的话你就必须指定好外部程序的完整路径。

调试技巧:

如果你正在运行 Linux 或者 Unix 操作系统,试一下按照下面的步骤手动运行一下脚本:

  1. 使 用 "su"、"sudo"或者类似的命令来切换到一般情况下可能会运行该脚本的用户。如果你运行的是
     Apache 服务器的话,那么这个用户通常是 httpd 或者 www-data。如果你运行 svnserve 的话,那么
     很可能是使用 svn 的帐户来运行该脚本。这样切换用户之后来运行脚本的好处就是不会再有脚本 运行权
     限错误的问题出现。
  2. 使用 env 程序清除所有环境变量然后再运行该脚本,如下所示:                           $ env -
     ./post-commit /var/lib/svn-repos 1234 注意到传递给 env 程序的第一个参数是一个横杠,这
     样可以保证环境变量为空。
  3. 查看控制台有没有输出错误信息。

为什么我的--diff-cmd 会有关于 ‘-u’的报错,我想用--extensions 去覆盖它,但是
不起作用。

当使用一个外部的 diff 命令时,Subversion 会生成一个非常复杂的命令行。第一个参数就是具体的--diff-
cmd,然后就是具体的 --extensions (尽管使用空白的 --符号时会忽略扩展),或者如果没有指定--
extensions 或者--extensions 为空的话,就加上‘-u’参数。第三和第四个参 数,Subversion 会传递一个“-L”还
有第一个文件的标签(例如,“"project_issues.html (revision 11209)”)。第五个和第六个就是另一个“-L”和
第二个文件的标签。第七和第八个参数分别是第一个和第二个文件的名称(例 如,“.svn/text-
base/project_issues.html.svn-base”和“.svn/tmp /project_issues.html.tmp”)。

如果你指定的 diff 命令不支持这些参数的话,你可能需要创建一个简单的封装脚本来忽略这些参数,然后将最后
的你需要的文件的路径参数传递给 diff 命令。

警告:Subversion 并不希望外部的 diff 工具会改变它接收到的文件,否则可能会破坏当前工作拷贝。

更多信息请参考 issue #2044.

啊呀,我刚刚发现我的 Subversion 客户端居然把我的密码以明文的方式缓存在本地
硬盘中!!!

冷静一下,深呼吸。

在 windows 2000 及之后的版本上,svn 1.2 之后的版本都使用标准的 windows API 来加密数据,所以只有用
户自己能够解密出缓存的密码来。

在 Mac OS X, svn 1.4 以后的版本使用系统的 keychain 功能来加密以及存储 svn 的密码。

Subversion 1.6 会为 UNIX/Linux 处理这个问题,对于 GNOME Keyring 和 KWallet 的支持已经实现,都可以
方便的在磁盘上存储加密的密码。这些程序可以在运行中的或编译中添加。如果没有,客户端会使用明文 缓存密
码,但是它如果以明文存储我们会首先询问是否允许。
Subversion FAQ
Subversion FAQ
Subversion FAQ
Subversion FAQ
Subversion FAQ
Subversion FAQ
Subversion FAQ
Subversion FAQ
Subversion FAQ
Subversion FAQ

Contenu connexe

En vedette

如何一整天有精神,保持微笑
如何一整天有精神,保持微笑如何一整天有精神,保持微笑
如何一整天有精神,保持微笑wensheng wei
 
Treebeard's Unix Cheat Sheet
Treebeard's Unix Cheat SheetTreebeard's Unix Cheat Sheet
Treebeard's Unix Cheat Sheetwensheng wei
 
保护数据库服务器加强数据库安全
保护数据库服务器加强数据库安全保护数据库服务器加强数据库安全
保护数据库服务器加强数据库安全wensheng wei
 
数据库系统安全防入侵技术综述
数据库系统安全防入侵技术综述数据库系统安全防入侵技术综述
数据库系统安全防入侵技术综述wensheng wei
 
mysql的字符串函数
mysql的字符串函数mysql的字符串函数
mysql的字符串函数wensheng wei
 
LINUX Admin Quick Reference
LINUX Admin Quick ReferenceLINUX Admin Quick Reference
LINUX Admin Quick Referencewensheng wei
 
JavaScript高级程序设计(中文优化版)
JavaScript高级程序设计(中文优化版)JavaScript高级程序设计(中文优化版)
JavaScript高级程序设计(中文优化版)wensheng wei
 
LINUX System Call Quick Reference
LINUX System Call Quick ReferenceLINUX System Call Quick Reference
LINUX System Call Quick Referencewensheng wei
 

En vedette (9)

创新项目
创新项目创新项目
创新项目
 
如何一整天有精神,保持微笑
如何一整天有精神,保持微笑如何一整天有精神,保持微笑
如何一整天有精神,保持微笑
 
Treebeard's Unix Cheat Sheet
Treebeard's Unix Cheat SheetTreebeard's Unix Cheat Sheet
Treebeard's Unix Cheat Sheet
 
保护数据库服务器加强数据库安全
保护数据库服务器加强数据库安全保护数据库服务器加强数据库安全
保护数据库服务器加强数据库安全
 
数据库系统安全防入侵技术综述
数据库系统安全防入侵技术综述数据库系统安全防入侵技术综述
数据库系统安全防入侵技术综述
 
mysql的字符串函数
mysql的字符串函数mysql的字符串函数
mysql的字符串函数
 
LINUX Admin Quick Reference
LINUX Admin Quick ReferenceLINUX Admin Quick Reference
LINUX Admin Quick Reference
 
JavaScript高级程序设计(中文优化版)
JavaScript高级程序设计(中文优化版)JavaScript高级程序设计(中文优化版)
JavaScript高级程序设计(中文优化版)
 
LINUX System Call Quick Reference
LINUX System Call Quick ReferenceLINUX System Call Quick Reference
LINUX System Call Quick Reference
 

Plus de wensheng wei

你会柔软地想起这个校园
你会柔软地想起这个校园你会柔软地想起这个校园
你会柔软地想起这个校园wensheng wei
 
几米语录(1)
几米语录(1)几米语录(1)
几米语录(1)wensheng wei
 
Installation of Subversion on Ubuntu,...
Installation of Subversion on Ubuntu,...Installation of Subversion on Ubuntu,...
Installation of Subversion on Ubuntu,...wensheng wei
 
高级PHP应用程序漏洞审核技术
高级PHP应用程序漏洞审核技术高级PHP应用程序漏洞审核技术
高级PHP应用程序漏洞审核技术wensheng wei
 
存储过程编写经验和优化措施
存储过程编写经验和优化措施存储过程编写经验和优化措施
存储过程编写经验和优化措施wensheng wei
 
CentOS5 apache2 mysql5 php5 Zend
CentOS5 apache2 mysql5 php5 ZendCentOS5 apache2 mysql5 php5 Zend
CentOS5 apache2 mysql5 php5 Zendwensheng wei
 
Happiness is a Journey
Happiness is a JourneyHappiness is a Journey
Happiness is a Journeywensheng wei
 
Java JNI 编程进阶
Java JNI 编程进阶     Java JNI 编程进阶
Java JNI 编程进阶 wensheng wei
 
Linux Shortcuts and Commands:
Linux Shortcuts and Commands:Linux Shortcuts and Commands:
Linux Shortcuts and Commands:wensheng wei
 
Java正则表达式详解
Java正则表达式详解Java正则表达式详解
Java正则表达式详解wensheng wei
 
Linux Security Quick Reference Guide
Linux Security Quick Reference GuideLinux Security Quick Reference Guide
Linux Security Quick Reference Guidewensheng wei
 
Android模拟器SD Card映像文件使用方法
Android模拟器SD Card映像文件使用方法Android模拟器SD Card映像文件使用方法
Android模拟器SD Card映像文件使用方法wensheng wei
 
如何硬盘安装ubuntu8.10
如何硬盘安装ubuntu8.10如何硬盘安装ubuntu8.10
如何硬盘安装ubuntu8.10wensheng wei
 
数据库设计方法、规范与技巧
数据库设计方法、规范与技巧数据库设计方法、规范与技巧
数据库设计方法、规范与技巧wensheng wei
 
揭秘全球最大网站Facebook背后的那些软件
揭秘全球最大网站Facebook背后的那些软件揭秘全球最大网站Facebook背后的那些软件
揭秘全球最大网站Facebook背后的那些软件wensheng wei
 
入门-Java运行环境变量的图文教程
入门-Java运行环境变量的图文教程入门-Java运行环境变量的图文教程
入门-Java运行环境变量的图文教程wensheng wei
 

Plus de wensheng wei (20)

你会柔软地想起这个校园
你会柔软地想起这个校园你会柔软地想起这个校园
你会柔软地想起这个校园
 
几米语录(1)
几米语录(1)几米语录(1)
几米语录(1)
 
我的简历
我的简历我的简历
我的简历
 
Installation of Subversion on Ubuntu,...
Installation of Subversion on Ubuntu,...Installation of Subversion on Ubuntu,...
Installation of Subversion on Ubuntu,...
 
高级PHP应用程序漏洞审核技术
高级PHP应用程序漏洞审核技术高级PHP应用程序漏洞审核技术
高级PHP应用程序漏洞审核技术
 
存储过程编写经验和优化措施
存储过程编写经验和优化措施存储过程编写经验和优化措施
存储过程编写经验和优化措施
 
CentOS5 apache2 mysql5 php5 Zend
CentOS5 apache2 mysql5 php5 ZendCentOS5 apache2 mysql5 php5 Zend
CentOS5 apache2 mysql5 php5 Zend
 
Happiness is a Journey
Happiness is a JourneyHappiness is a Journey
Happiness is a Journey
 
Java JNI 编程进阶
Java JNI 编程进阶     Java JNI 编程进阶
Java JNI 编程进阶
 
Linux Shortcuts and Commands:
Linux Shortcuts and Commands:Linux Shortcuts and Commands:
Linux Shortcuts and Commands:
 
Java正则表达式详解
Java正则表达式详解Java正则表达式详解
Java正则表达式详解
 
Linux Security Quick Reference Guide
Linux Security Quick Reference GuideLinux Security Quick Reference Guide
Linux Security Quick Reference Guide
 
issue35 zh-CN
issue35 zh-CNissue35 zh-CN
issue35 zh-CN
 
Android模拟器SD Card映像文件使用方法
Android模拟器SD Card映像文件使用方法Android模拟器SD Card映像文件使用方法
Android模拟器SD Card映像文件使用方法
 
如何硬盘安装ubuntu8.10
如何硬盘安装ubuntu8.10如何硬盘安装ubuntu8.10
如何硬盘安装ubuntu8.10
 
ubunturef
ubunturefubunturef
ubunturef
 
数据库设计方法、规范与技巧
数据库设计方法、规范与技巧数据库设计方法、规范与技巧
数据库设计方法、规范与技巧
 
揭秘全球最大网站Facebook背后的那些软件
揭秘全球最大网站Facebook背后的那些软件揭秘全球最大网站Facebook背后的那些软件
揭秘全球最大网站Facebook背后的那些软件
 
入门-Java运行环境变量的图文教程
入门-Java运行环境变量的图文教程入门-Java运行环境变量的图文教程
入门-Java运行环境变量的图文教程
 
Java学习路径
Java学习路径Java学习路径
Java学习路径
 

Subversion FAQ

  • 1. Subversion FAQ 本文根据原文 r33959,由 Subversion 中文站的中文化翻译小组翻译,欢迎各位参与翻译工作,加入地址: http://code.google.com/p/svncndoc/。参与翻译的志愿者包括 rocksun、akeybupt2004、zhaozhi 和 jiaqifeng。 常见问题: • 为什么会有这样一个项目? • Subversion 是私有软件吗?我听说它是属于 CollabNet 公司的。 • Subversion 用在我的项目上是否足够稳定? • Subversion 的客户端/服务器在协同工作时的策略是怎样的? • Subversion 可以运行在哪些操作系统上? • 所有它的一切是否是一种新的文件系统?比方说 ext2 文件系统? • 为了运行一个 Subversion 服务器,哪些硬件是我所需要的? • 我听说 Subversion 是 Apache 项目的扩展?我是否需要 Apache 来做服务器呢? • 是否意味着我必须首先安装 Apache 才能使用 Subversion? • 我现在所运行的是 Apache 1.x,但是我不能仅仅为了支持 Subversion 版本库而将其转换成 Apache 2.0。这是否意味着我不能使用 Subversion 服务器? • 为什么不象 SCM 系统 Y 那样来做 X? • 为什么全部的库都使用相同的修订版本号码?我想让我的每一个工程都有其自己的修订版本号码。 • Subversion 有没有变更集? • 下一个版本什么时候发布? • Subversion 是否支持符号链(symlinks)? • 我需要一个高分辨率的 Subversion Logo,从哪里可以得到它呢? • 我还有些其他的问题,我从哪里可以得到更多的相关信息? • 为什么我的邮件没有显示在邮件列表上? 如何使用: • 怎么样检出 Subversion 版本库里的代码? • 怎么样创建一个版本库?怎样将数据导入到版本库中? • 怎么样将已经存在于 CVS 版本库中的代码转换并导入到 Subversion 版本库中? • 我必须通过代理访问网络,我该怎么办? • 我的管理员不想让我有一个 Subversion 的 HTTP 服务器,那么如何做我才可以远程使用? • 如何在同一个版本库里管理几个不同的项目? • 我如何合并两个完全分开的版本库? • 我必须在 NFS 服务器上存储版本库/工作拷贝吗? • 为何我的版本库占去这么多的磁盘空间? • 我如何恰当的设置我的版本库的权限呢? • 为何只读的操作仍然需要版本库的写访问? • 如何完全的从版本库历史中删除一个文件? • 一个版本提交之后,如何修改其日志信息? • 怎么样向 Subversion 提交一个补丁? • 我如何进行“iplace”的导入(例如:向 Subversion 添加一个目录结构,而原先的数据直接成为工作拷 贝)? • 人们在讨论升级 Subversion 时所说的“转储/加载(dump/load)”是什么? • 如何设置客户端通过使用 SSPI 认证的 Windows 域控制器进行认证? • 我不喜欢“.svn”这样的目录名字,而喜欢“SVN”或者其他一些目录名,我该如何改变呢? • 如何更改一个文件名的大小写? • 我不能象 CVS 那样使用标签将一个分支的变更合并到主干(trunk),可以吗? • 为什么$Revision$关键字不是我预想的那样?它替换的是文件最后修改的修订版本,但有时候我希望它 能替换文件的当前修订版本。 • Subversion 是否有一个功能类似 CVS 的$Log$的关键字呢?
  • 2. 在我的工程里有一个文件,每个人都必须改变它,但是我不希望他们本地的修改被提交,如何让'svn commit'忽略这个文件? • 当我通过 svn+ssh 来访问一个版本库的时候,我的密码没有被缓存在~/.subversion/auth/,我应该如 何避免每次都要键入密码? • 我的 svnserve 二进制程序不在我的用户的默认路径中,他们使用 svn+ssh,我不知道怎样修改他们的 路径来让他们运行 svnserve。 • 我希望允许通过 svn+ssh://来访问版本库,但我很忧虑。我讨厌为每个用户分配一个登录帐号的方法, 那样我会为他们是否被允许访问我的机器感到担心。 • 我怎么才能为版本库的所有文件设置一个的属性?另外,我该如何确保每个添加到版本库里的新文件都有 这些属性? • 我如何处理编辑器路径中的空白?另外,如何定义编辑器的命令行选项? • 如何确定版本库正在使用的 Berkeley DB 的版本? • 我在版本库中管理了一个网站,如何才能实现每次提交之后站点自动更新? • 我如何检出一个单独的文件? • 如何在工作拷贝执行完添加、删除、拷贝和重命名操作之后检测这些操作? • 在 Windows 上如何将 svnserve 当作服务来运行? • 如何转换我的版本库,从 BDB 到 FSFS,或者从 FSFS 到 BDB? • 版本库如何处理二进制文件? • 如何让 svn diff 仅显示被改变的文件的名字,而不是连内容也显示出来? • 我能否用通配符或者点符号来一次性移动多个文件? • 我如何用 Subversion 维护一个第三方不断修正的软件呢?("供方分支")? 疑难解答: • 我的版本库经常看起来卡住了,一直报一个需要重新恢复(DB_RUNRECOVERY)的错误,怎么会导致这 个问题? • 每次我想访问我的版本库,进程就会挂起。我的版本库坏掉了吗? • 我的版本库一直报告错误"Cannot allocate memory",我该怎么办? • 每当我试图运行一个 svn 命令时,都会提示我的工作拷贝已经被锁定了,是我的工作拷贝坏掉了吗? • 我试图去提交,但是 Subversion 提示我的工作拷贝已经过时。 • 我为项目贡献了一个补丁,而这个补丁添加了一个新文件,现在 svn update 不能工作了。 • 我刚刚编译了分发二进制程序,但是当我试图检出版本库时,我得到一个错误“Unrecognized URL scheme”。这是怎么回事呢? • 当我查找或打开一个版本库时出现错误,但是我知道我版本库 URL 是正确的,哪里出错了? • 当我运行‘configure’命令时,出现一些错误 subs-1.sed line 38: Unterminated `s' command,这 是怎么回事? • 我在 Windows 下用 MSVC++6.0 构建 Subversion 时候有些麻烦,我该怎么办? • 如何在 file:协议的 URL 中指定 Windows 盘符?file: URL? • 我在通过网络对 Subersion 版本库进行写操作的时候有些麻烦。 • VS.NET/ASP.NET 在处理".svn"目录名时好像有些问题,我该怎么办? • 在 Windows XP 下,Subversion 服务器有时候会发布一些错误数据,真的是这样吗? • 在 Subversion 服务器和客户端之间进行交互时,跟踪网络的最好方法是什么? • 为什么 svn revert 要求有一个明确的目标?为什么它默认不是递归执行的呢?这与所有其他的子命令都 不同。 • 当我启动 Apache 时,mod_dav_svn 报告"bad database version",它发现的是 db-3.X,而不是 db-4.X。 • 在 Red Hat 9 上,我得到一个"Function not implemented"错误,一切都停止工作。我该如何修正它 呢? • 为什么在文件在通过 Apache(ra_dav)被提交和导入时,SVN 的日志说"(no author)"? • 我在 Windows 平台上偶尔会得到一个"Access Denied"错误,它的发生好像没有什么规律,为什么呢? • 在 FreeBSD 上,某些操作(尤其是 svnadmin create)有时候会被挂起。为什么? • 我可以从一个 WEB 浏览器上查看我的版本库,但是在执行'svn checkout' 时发生一个错误:"301 Moved Permanently"。那个地方出错了? • 为什么 HTTP 的 Digest 认证不能工作? • 在 AIX 上通过 xlc 编译文件,出现了一些编译错误?怎么回事呢?
  • 3. 我用非递归方式(通过-N 选项)检出了一个目录,现在我想让某个子目录“出现”,但是 svn up subdir 不起作用。 • 我试图在 Win32 平台 Apache 服务器上使用 mod_dav_svn,但是我得到找不到 module 的错误,而 mod_dav_svn.so 文件确实处在Apachemodules 下。 • 为什么我的版本库钩子不工作? • 为什么我的--diff-cmd 会有关于‘-u’的报错,我想用--extensions 去覆盖它,但是不起作用。 • 啊!我发现我的 Subversion 客户端在磁盘上以纯文本的形式缓存了密码!啊! • 我得到一个错误"svn: bdb: call implies an access method which is inconsistent with previous calls"。我该如何修正它呢? • 我无法热备份我的版本库,当文件大于 2Gb 时 svnadmin 会出错。 • 我看不到我刚刚提交的文件的日志记录,为什么呢? • 升级到 Berkeley DB 4.3 或更新的版本之后,版本库出错了。 • 当我通过 http://从 MacOS X 10.4 (Tiger)的平台上检出版本库的时候,为什么偶尔会得到一些不一致 的错误? • 我不能构建 Subversion,我的工作拷贝源码在 Debian GNU/Linux 上,在链接阶段我得到了一些错 误,哪里错了呢? • 我在使用 FreeBSD,并且已经启动了 svnserve,但是看起来并没有监听 3690 端口。 • 我不能添加一个目录,因为 Subversion 说“它已经处于版本控制了”。 • 有时候通过 svnserve 访问一个非公开的版本库实在是太慢了。 • 当执行的 Subversion 操作需要通过 SSL 传递大量数据的时候,碰到一个错误 SSL negotiation failed: SSL error: decryption failed or bad record mac。 • 我得到一个错误"This client is too old"。 • 为什么有时候 svn switch 不能工作? • 在 Windows 平台上,通过命令行客户端的执行更新操作时,我碰到一个错误"The system cannot find the path specified",并且提示说我的工作拷贝可能损坏了,但是我能通过 TortoiseSVN 更新时完全正 常,这是怎么回事呢? • 我碰到一个错误"This client is too old to work with working copy '...' ",不升级 Subversion 能够 解决吗? • 当我在 64 位 Linux 上编译 Neon 库时,发生一个错误"relocation R_X86_64_32 against `a local symbol' can not be used when making a shared object"。 • 为什么从 Apache 检出时得到“Could not read response body: Secure connection truncated”的 错误? 开发者问题 • 怎样在 RAM 磁盘上进行回归测试? • 怎样在不安装的情况下对动态 Subversion 库运行调试器? • 怎样让编译器不内联混淆(inlining obfuscating)源代码的情况下对 Subversion 库运行调试器? 说明: • Subversion 用到的 HTTP 方法是有哪些? • 什么是'bikeshed'? • 你是怎样读"Subversion"的? • 什么是'baton'? • 当你说版本库是'楔住(wedged)'的时候,是什么意思? 常见问题: 为什么会有这样一个项目? 为了接管 CVS 的用户基础。确切的说,我们写了一个新的版本控制系统,它和 CVS 很相似,但是它修正了以前 CVS 所没有解决的许多问题。请看我们的首页。
  • 4. Subversion 是私有软件的吗?我听说它是属于 CollabNet 公司的。 不是,Subversion 一款开源/免费的软件。CollabNet 公司为几个全职的开发人员支付薪水,并且拥有相关代码 的版权,但是这个版权是一个 Apache/BSD-风格的许可证,它完全遵从于 Debian Free Software Guidelines。换句话说,你可以随心所欲的去下载,修改,或者重新发布新的版本,而不需要经过 CollabNet 公 司或者其他任何一个人的许可。 Subversion 用在我的项目上是否足够稳定? 是的,绝对可以。它是一款已经准备好进入黄金时段的产品。 Subversion 从 2000 年开始开发,在一年之后成为一个自足执行(self-hosting)的项目。在之后的一年,当我们 将其称 为"alpha"版本的时候,Subversion 已经被很多的个人开发人员所使用,并确实发挥了真正的作用。在那 之后,有两年多的时间被用来进行 Bug 追踪(bugfixing)和增强稳定性(stabilization),直到我们发布了 1.0 版 本。大多数的其它项目可能都会把产品的“1.0”版本叫 做早期版本,但是我们故意的尽可能长的推迟了这个版本 的发布。我们意识到很多人在他们最初使用了 Subversion 之后一直在等待 1.0 版本的发布,并 且对这个意义非 凡的版本有着特别的期待,所以我们在这样一个版本上用了很多的时间而不至于让他们失望。 Subversion 的客户端/服务器在协同工作时的策略是怎样的? 客户端和服务器被设计成只要他们相互之间没有超过一个主要的发行版本,就可以协调工作。例如任何一个 1.x 的客户端都可以和一个 1.y 的服务器协调工作。然而,如果客户端和服务器的版本不相匹配,某些特性可能不能 使用。 客户端和服务器之间的兼容性策略记录在 Hacker's Guide to Subversion 的“兼容性”一节里面。 Subversion 可以运行在哪些操作系统上? 所有现代风格的操作系统,比如 Unix, Win32, BeOS, OS/2, MacOS X。 Subversion 是用 ANSI C 来写的,并且使用了 APR,也就是 Apache Portable Runtime 库 作为可移植 层。Subversion 的客户端将可以运行在任何 APR 运行的地方,这是最重要的一点。Subversion 服务器(例 如,版本库端)同样, 唯一的例外是在 Berkeley DB 的 Win9x(Win95/Win98/WinME)作为平台的主机上,因 为 Berkeley DB 在 Win9x 平台上共享存储器的有段问题。FSFS 版本库(从版本 1.1 开始引入)没有这种限制; 然而由于 Win9x 对文件锁定的支持限制,他们仍然 不能在 Win9x 的平台上工作。 重申一下,Subversion 客户端可以运行在任何 APR 所运行的平台上。Subversion 服务器也可以运行在任何 APR 平台所能运行的平台,但是不能在 Win95/Win98/WinMe 上管理版本库。 所有它的一切是否是一种新的文件系统?比方说 ext2 文件系统? 不是。"Subversion 文件系统"不是一个可以装在操作系统上的内核级的文件系统,相反,它是 Subversion 版本 库的接口,是一个版本 文件系统,在某种意义上说,它可以存储一个文件目录结构(树)并且使这个目录结构从 一个修订版本到下一个修订版本的过程中保留版本信息。访问这个版本库来 编写程序和使用其他文件系统的 API 是很相似的,但是最大的不同在于,这个特殊的文件系统在你写入的时候不会丢失数据。目录结构(树)的一些旧 的状态信息 可以被很容易的恢复,就像恢复到最近的状态那样容易。 为了运行一个 Subversion 服务器,哪种硬件是我所需要的? 运行 Subversion 服务器要依赖各方面的多种因素,比如说一定数量的用户,经常性的提交,其它相关联的服务 器,版本库的大小以及自定义版本库 的负载等。当使用 Apache 时,有可能 Apache 本身在内存的使用情况将成 为最大的制约因素。请参阅邮件列表上对这个问题的讨论,这里有针对这个问题的明确的答案。
  • 5. 需要记住的是,在同一台服务器上运行其它的应用程序,比如版本库的浏览器同样会使用内存,它是独立于 Subversion 本身。 通常,和 CVS 本版库相比,你可以期望需要更少的服务器内存。 我听说 Subversion 是 Apache 项目的扩展?我是否需要 Apache 来做服务器呢? 不用。Subversion 是一系列的库,它与一个命令行的客户端相互配合工作。有两类不同的 Subversion 的服务器 进程,包括一个 svnserve 进程,这是一个小的类似 CVS 的 pserver 进程的独立运行程序,另一个是使用 mod_dav_svn 模块的 Apachehttpd-2.0。svnserve 进程可以说是一个常用协议,而 mod_dav_svn 进 程使用了 WebDAV 作为它的网络协议。请参阅 Subversion 手册第六章以了解更多的内容。 是否意味着我必须首先安装 Apache 才能使用 Subversion? 一句话:不必。 详细的回答是:如果你仅仅是想去访问一个版本库,你只需要构建一个 Subversion 的客户端。如果你想拥有一 个网络的版本库,那么你需要安装 Apache2 或者一个“svnserve”服务器。 关于安装一个可以访问的 Subversion 服务器的详细信息,请参阅:Subversion 手册第六章。 我现在所运行的是 Apache 1.x,但是我不能仅仅为了支持 Subversion 版本库而将 其转换成 Apache 2.0。这是否意味着我不能使用 Subversion 服务器? 不必,你可以用 svnserve 作为 Subversion 的服务器,它可以很好的工作。 在使用 Apache server 时,如果你想使用分布式创作和版本管理协议(WebDAV)和所有其他一些好的功能特 性,那么是的,你需要 Apache 2.0。但是不管怎样,当你继续在 80 端口运行 Apache1.0 的时候,你总是可以 在另外一个不同的端口运行 Apache2.0。不同版本的 Apache 可以在同一台机器上很好的和平相处。仅仅需要在 改变 httpd.conf 文件中把 Listen 指令从 80 改成 8080,或者其他你想要改成的端口。然后确保在你公布版本库 的 URL 的时候加以说明:(例如,http://svn.mydomain.com:8080/repos/blah/trunk/)。 为什么不象 SCM 系统 Y 那样来做 X? 我们从来没有试图在 SCM 系统上推到重来,开辟出一个新的天地,也没有试图完全模仿每一个 SCM 系统的好的 特性,我们只是要取代 CVS。请参阅我们的第一个问题。 为什么整个库都使用相同的版本号码?我想让我的每一个工程都有其自己的版本号。 首先,请注意 Subversion 没有项目这个概念。版本库只是存储版本化的目录树 — 你可以将某个子目录当作项 目,但是 Subversion 不会对其特殊对待。因此,对于一个项目的构成完全由用户自己解释。(与之类似的 branches 和 tags 的习惯是建立在复制之上,而不是建立在 Subversion 的概念之上。) 每当你提交变更时,版本库会在版本库目录树整体上增加一个修订版本,并将新的树赋予一个新的修订版本号, 当然,大多数目录树和前一个修订版本完全一样,只是部分被更改。 新修订版本号码是一个顺序增加的标签,会附加给每个新增的树,而不是这个修订中的某个文件或目录,然而, 通俗来说,会使用修订版本号码来引用修订中 提交的变更;例如“r588 中的变更”(“r588”是“修订版本 588”的 简写)的真实含义是“版本库目录树 587 和 588 的区别”,或者是另一个说法 “将目录树 587 变成 588 的变更”。
  • 6. 因此,不断增加的修改版本号码会以一个整体标示版本库的进展;你通常不会使用修订版本号码来度量版本库中 特定项目的进展,当然,修订版本号码不应该作为项目可见的发布号码,对此,你应该通过其他机制来区别发 布,例如使用 tags。 Subversion 是否有变更集? 这个问题有些麻烦,因为好像每个人对变更集的定义多少有些不同,或者至少对版本控制系统的变更集特性多少 有些不同的期望。 基于这个讨论的目的,这里对变更集有一个简单的定义:它是所有改变的唯一的名字的集合,这些改变可能包括 对文件内容句法的编辑,目录结构的改变,或者是一些元数据的重新组合。更加通常的理解,一个变更集仅仅是 一个你所能进行参阅的补丁的名字。 Subversion 按照一阶对象的方式管理版本化目录树(版本库是一个目录树数组),而变更集则是被推生出来的东 西(通过比较相邻的目录树)。 Arch 或 Bitkeeper 这类程序以相反方向创建:他们用一阶对象的方式管理变更 集(版本库是一系列的补丁),而目录树则是由一系列的补丁组合而成。 从根本上来说,两者都不够好:争论至少可以追溯到三十年以前。对于不同类型的软件开发,各有利弊。现在我 们不打算讨论这些,这里我将解释使用 Subversion 能怎么做。 用 Subversion,用一个全局的版本编号 N 来命名版本库目录树:这是说版本库是经过第 N 次提交。它还包括一 些不明显的变更集:如果你比较目录树 N 和目录树 N-1,你可以精确得到提交的补丁。 因此,可以很容易的想到,版本 N 不仅仅是一个变更集。如果你用一个事件追踪去管理 bug,你可以用版本号码 去引用特殊的补丁,这些补丁很适合 bug。例如,“这个事件被稳定在 9238 版本。”一些人可能运行‘svn log -r9238’来阅读对应 Bug 的补丁信息,运行‘svn diff -r9237:9238’来查看补丁本身。svn 合并命令也是利用了 版本号码。只要在合并参数中指明结果集,就可以把结果集从一个分支明确的合并到另一个 分支:‘svn merge - r9237:9238 branchURL’将合并结果集#9238 到你的工作拷贝。 似乎根据结果集构建和主要对象的构建一样复杂,但是已经比 CVS 方便许多了。 下一个版本什么时候发布? 看我们的状态页 http://subversion.tigris.org/project_status.html。 Subversion 是否支持符号链? Subversion 1.1(和后续版本)已经可以把一个符号链置于版本控制之中,通过一个常用的 svn add 命令即 可。 详细:版本库还没有一个关于符号链的内部概念,它存储一个附加'svn:special'属性的普通文件作为“符号链 接”。svn 客户端(在 unix 上)可以看到属性,并且在工作拷贝里转换成一个符号链。Win32 没有符号链,所以 一个 win32 的客户端不会做任何的转换:对象表现的像一个平 常的文件。 我需要一个高分辨率的 Subversion Logo,从哪里可以得到它呢? 可用的矢量 Subversion logo 在 Subversion 版本库的 www 文件夹下可以得到。 特别的是,EPS 版本,和一个 Adobe 插图文档也是可用的。
  • 7. 我还有其他的一些问题,我从哪里可以得到更多的信息呢? 如果你在阅读这个常见问题回答之后,没有找到你问题的答案,那么你还有其他的几个资源可以利用: • Subversion 手册,以及中文手册 Subversion 手册 • The Subversion 用户邮件列表 (users@subversion.tigris.org) — 注意这个列表需要经过审核,所以 在显示之前有一些延迟。 • Subversion 用户信息列表。 • 在线聊天系统(IRC)在 irc.freenode.net 的#svn 频道。 • svnforum.org 一个非官方基于网络的论坛,针对的读者和邮件列表近似。 为什么我的邮件没有显示在邮件列表上? 我们的邮件列表为了保持在一个适度的标准,所以你最初的邮件可能会被延迟通过,直到维护人员有机会让它通 过。一旦邮件允许通过,所有从相同的地址挂起的邮件将被自动支持,所以你应该不会再被拒绝。当然,如果你 的发送地址改变了的话,你将不得不再次让维护人员检测通过。 如何: 我如何才能检出 Subversion 版本库里的代码? 使用 Subversion 客户端: $ svn co http://svn.collab.net/repos/svn/trunk subversion 这将会从 Subversion 源文件目录里检出一个名叫 subersion 的目录到你的本机上。 我如何创建一个版本库呢?并且我又该如何向里导入数据呢? 请参阅 http://svn.collab.net/repos/svn/trunk/README;特别的,在第 IV 部分,即“快速指南”。 更详细的资料,请阅读 Subversion 手册第五章。 我如何把一个现存的 CVS 版本库转换成 Subversion 版本库? 试一下 cvs2svn 转换工具,从 http://cvs2svn.tigris.org/ (或者从这里 特性列表和相关文档)。cvs2svn 是大 多数人的选择,但是如果有别的原因使他不能满足你的要求,至少还有其他两种工具供你选择: • 一个是基于 VCP,由 Chia-liang Kao 编写,可以在 CPAN 找到。 • 另一个由 Lev Serebryakov 写的 refinecvs,在 http://lev.serebryakov.spb.ru/refinecvs/上面可 以找到。 也可以参阅 Subversion 链接页面。 我必须通过代理访问网络,我该怎么办? Subversion 支持通过代理访问网络。首先,修改配置文件中的"servers"部分,并指定你的代理服务器。配置文 件所在目录在不同的操作系统上可能不同,在 Linux 或 Unix 系统中,通常是~/.subversion;在 Windows 系统 中,通常是"%APPDATA%Subversion"。(执行"echo %APPDATA%"显示目录的具体路径,注意这是一个 隐藏目录。) 配置文件中的注释描述了配置文件书写的格式。如果配置文件还不存在,可以取得最新版的 svn,并执行任何 svn 命令,这将创建配置文件模板及其相应的目录。
  • 8. 其次,请确认你的代理服务器支持所有 Subversion 必须的 HTTP 方法。有些代理服务器默认不支持以下命令: PROPFIND, REPORT, MERGE, MKACTIVITY, CHECKOUT。解决办法依赖于你使用的代理服务器软件,对于 Squid,配置选项如下: # TAG: extension_methods # Squid only knows about standardized HTTP request methods. # You can add up to 20 additional "extension" methods here. # #Default: # none extension_methods REPORT MERGE MKACTIVITY CHECKOUT (Squid 2.4 及其之后的版本支持 PROPFIND.) 参见"Subversion 用到的 HTTP 方法是有哪些?"来配置代理服务器来支持 HTTP 方法。 如果让代理服务器支持 Subversion 访问网络很困难甚至是不可能的话,而你只想 checkout Subversion 的源 代码,你可以绕过代理服务器。一些代理服务器封锁了 80 端口,如果是这样的话,可以通过 81 端口访问 svn.collab.net 代码库服务器。执行: svn checkout http://svn.collab.net:81/repos/svn/ trunk subversion 可能代理服务器会放行。另一个办法是通过 SSL 来 checkout,SSL 被大部分代理服务器所支持: svn checkout https://svn.collab.net/repos/svn/trunk subversion 当然,你的 svn 客户端应该支持 ssl。在编译源代码的时候,在./configure 时添加--with-ssl 选项。执行 svn -- version 可以知道你的 svn 是否支持'https'。 我的管理员不想让我有一个 Subversion 的 HTTP 服务器,那么如何做我才可以远程 使用? 一个简单的选择是使用 svnserve 服务器来代替。请参阅 SVN 手册第 6 章中的详细内容。 然而,如果你的管理员不希望你运行 Apache,这很可能是他们不想让你在 3690 端口运行一个客户服务器,则备 选答案是假定你的管理员同意你使用现有的 SSH 设施。 如果你使用 CVS,你可能已经使用 SSH 来登录 CVS 服务器,ra_svn Subversion 的访问方法是和使用 Subversion 是相同的。仅仅是在你的版本库的 URL 上加上一个"svn+ssh"的前缀。 $ svn checkout svn+ssh://your.domain.com/full/path/to/repository 这将使你的 SSH 的程序在远程运行一个私有的'svnserve'进程,用你的用户 ID 访问版本库,并通过加密管道将 数据传递回来。 然而,另外的一种可以用来替代的解决方案是将 SSH 端口转向连接到通过 ra_dav 保护的服务器上。你可以通过 SSH 连接到一个防火墙后的一个机器,这个机器可以访问 Subversion 服务器。注意,这个 SSH 服务器不需要 与 Subversion 安装在同一个机器上,可以是,但不是必须是。 然后你可以创建一个本地端口来连接在你家里的 Subversion 版本库的 HTTP 服务器。你可以通过本地端口’连 接‘Subversion 版本库。然后,请求将被通过 SSH 服务器’通道‘发送到你的 Subversion 服务器。 一个示例:在你们公司位于 10.1.1.50(叫它 svn-server.example.com)的防火墙后面设置了一个 Subversion ra_dav,你的公司允许 SSH 通过公共方式访问 ssh-server.example.com,而在内部可以通过 http://svn- server.example.com/repos/ours 访问 Subversion 版本库。
  • 9. 实例:那么客户端通过端口转向连接 ssh 服务器,并通过端口转向检出 % ssh -L 8888:svn- server.example.com:80 me@ssh-server.example.com % svn checkout http://localhost:8888/repos/ours 请注意 svn-server.example.com 也可以让 httpd 实例被非信任用户运行在无特权的端口上,这允许 Subversion 不需要 root 访问权限。 Joe Orton 注明 服务器对正在使用的 MOVE 和 COPY 请求头的主机名字是很敏感的,所以这个地方你必须要小心 —工作正常可能需要配置"ServerAlias localhost"。 一些 SSH 端口转向的链接 • http://www.onlamp.com/pub/a/onlamp/excerpt/ssh_11/index3.html • http://csociety.ecn.purdue.edu/~sigos/projects/ssh/forwarding/ • TTSSH: A Win32 SSH client capable of port forwarding 我如何在 Subversion 下面管理几个不同的项目? 这决定与你的项目的复杂度,如果你的项目是相关的,并且有可能要共享数据,那么最好的方式是通过子目录创 建一个版本库。像下面这样子: $ svnadmin create /repo/svn $ svn mkdir file:///repo/svn/projA $ svn mkdir file:///repo/svn/projB $ svn mkdir file:///repo/svn/projC 如果你的工程是完全不相关的,并且他们之间不可能共享数据,这样最好创建几个独立的完全不相关的版本库。 $ mkdir /repo/svn $ svnadmin create /repo/svn/projA $ svnadmin create /repo/svn/projB $ svnadmin create /repo/svn/projC 这两种方式之间不同之处在于: (由 Ben Collins-Sussman 解释 <sussman@collab.net>): • 在第一种情况之下,代码可以很容易的在两个项目之间拷贝和移动,并且操作的历史记录会被保存下来。 ('svn cp/mv'现在只能在单个版本库中工作。) • 因为修订版本号是版本库范围的,在第一种情况下,对任何项目的提交都可能造成全局的版本冲突。所以 如果有个人检出了‘projB’,并发现已经发生的 10 次修订,但是 projB 没有完全改变,这看起来有些奇 怪。事实上,这无关紧要,只是一开始会感到有些奇怪。这就像每当人们向 rapidsvn 提交,而 rapidsvn 和 svn 在同一个版本库之下时,svn 的状况。:-) • 第二种情况可能更利于安全管理吗;可以很容易的使用 Apache 访问控制将每个项目隔绝(就用户和许可 的角度来讲)。在第一种情况下,你需要在版本库放一 个钩子脚本来区分不同的项目(“是否允许用户在 特定的子目录提交?”)当然,我们已经准备了这些脚本供你使用。 我如何合并两个完全分开的版本库? 如果你不在意某个版本库的完全历史,你可以只是在某个版本库为另一个项目创建一个新的目录,然后导入另一 个项目。
  • 10. 如果你在意两边的历史,那么你可以使用'svnadmin dump'将一个版本库的内容转储出来,然后使用'svnadmin load'加载到另一个版本库。原来的修订版本号码会取消,但你还有历史。 Peter Davis <peter@pdavis.cx>也解释了一种方法,可以使用像 CVS 模块那样使用 svn: 只要合并发生在不同的目录树,你可以使用 svn 版的 CVS 模块。 将 svn:externals 属性设置到从其他版本库检出的目录上,无论原来的目录是何时检出的。版本库还是分离的, 但是从工作拷贝的角度看,他们好像合并了。如果你在导入的目录中提交,也将会影响外部版本库。 合并并不意味着完全的干净:导入只是影响了工作拷贝,所以你应该不能使用第一个版本库的 URL 访问从第二个 导入的模块,他们都还是有各自的 URL。 也可以看 miscellaneous utilities,里面有一些在合并不同版本库时帮助选择和重排序修订版本的工具,特别如 基本操作的 perl 脚本 svn-merge-repos.pl 和高级组织的 python 类 SvnDumpTool。 我必须在 NFS 服务器上存储版本库/工作拷贝吗? 如果你使用 Berkeley DB 作为版本库的后端(在 Subversion 1.0 和 1.1 这是默认值,此后不是默认值),我们 建议你不要将 版本库存放在远程文件系统(例如,NFS)。虽然 Berkeley DB 数据库和日志文件可以存放到远 程文件系统,但是 Berkeley DB 的共享区域文件不可以放到远程文件系统上,所以版本库只有被一个文件系统客 户访问时才能保证安全,而且那种情况下并不是所有的 Subversion 功 能都在一个客户下工作正常。 如果你使用 FSFS 作为后端,那么将版本库存放到 NFS 服务器(应当是支持锁定的服务器)也应当没问题。 工作拷贝可以存放到 NFS(一个常见的场景是你的主目录在 NFS 服务器上)上,在 Linux NFS 服务器上,因为 在检出时 Subversion 内部使用的重命名的量比较大,一些用户报告应当关闭‘子目录检查(subtree checking)’应当关闭,如果关闭子目录检查的详细信息可以看 NFS Howto Server Guide 和 exports(5)。 我们至少接到一份对于通过 SMB 访问造成工作拷贝楔住的报告,造成错误的服务器是版本非常老的 Samba(2.2.7a),在新版本(3.0.6)Samba 中并没有再出现这个问题。 为何我的版本库占去这么多的磁盘空间? 在 Berkeley DB 环境中,版本库会在 repos/db/子目录存放所有的数据,这个环境会包含一组表和一组日志文件 (log.*)。Berkeley DB 会记录对表所作的变更,这样在出现中断后能够恢复到一致的状态(more info)。 如果你放任不管(作为版本库管理员),日志文件会不断的生长,吞噬磁盘空间。在任何时刻,Berkeley DB 只 使用很小一部分的日志文件(可以看这个帖子以及相关的线索);其余的可以安全的删除。如果你永久保存所有 的日志文件,理论上 Berkeley DB 能够根据这个文件回到出生的时刻。但是在实践中,如果你进行了备份,就没 有必要在磁盘中浪费空间了。 可以使用 svnadmin 查看哪些日志文件可以删除,你可以通过 crob 程序完成这个任务。 $ svnadmin list- unused-dblogs /repos /repos/db/log.000003 /repos/db/log.000004 [...] $ svnadmin list-unused-dblogs /repos | xargs rm # disk space reclaimed!
  • 11. 你也可以使用 Berkeley DB 的 db_archive 命令: $ db_archive -a -h /repos/db | xargs rm # disk space reclaimed! 还可以看 svnadmin hotcopy 或 hotbackup.py。 注意:如果你正在使用 Berkeley DB 4.2,Subversion 创建的版本库会自动删除日志文件,如果你想关闭这个 功能,可以在 svnadmin create 命令中使用--bdb-log-keep 选项。可以参考 Berkeley DB 手册中的 DB_LOG_AUTOREMOVE 参数。 我如何恰当的设置我的版本库的权限呢? 试图保证尽可能少的用户能够访问版本库,例如以某个用户运行 apache 或'svnserve -d',那么版本库由这个用 户完全拥有。不允许任何其他的用户通过 file:///的 URL 访问版本库,必须只让拥有版本库的用户运 行'svnlook'和'svnadmin'。 如果你的客户端通过 file:///或 svn+ssh://访问,则无法避免多个用户的访问。在那种情况下,可以阅读第 6 章 最后一小节,看一下最下面工具栏的“检查列表”,它总结了让这个场景更安全的步骤。 SELinux / Fedora Core 3+ / Red Hat Enterprise 的用户注意: 作为标准 Unix 许可的补充,在 SELinux 下,每个文件、目录和进程都有一个‘安全上下文’。当进程试图访问一个 文件时,除了检查 Unix 访问许可,系统还会检查进程的安全上下文与文件的安全上下文是否兼容。 而 Fedora Core 3,随 SELinux 一起安装,在默认情况下 Apache 会在一个限制的安全上下文中运行。为了在 Apache 下运行 Subversion,你必须设置版 本库的安全上下文使之支持 Apache 的访问(或者关闭对 Apache 的限制,如果你认为这是过分小心)。chcon 命令可以用来设置文件的安全上下文(与 chmod 设置 Unix 访问许 可类似)。例如,一个用户可以这样运行命令 $ chcon -R -h -t httpd_sys_content_t PATH_TO_REPOSITORY 设置安全上下文可以成功的访问版本库。 为何只读的操作仍然需要版本库的写访问? 某些客户端操作是“只读的”,例如检出和更新。从访问控制的角度,Apache 会这样处理。但是 libsvn_fs(版本 库文件系统 API)在生成增量树的时候还是需要写临时数据,所以访问版本库的进程应该能够读写访问 Berkeley DB 的文件,才能完成功能。 尤其是版本库需要应答许多比较两个目录树的“只读”操作时,一个树可能是 HEAD 修订版本,而另一个则是临时 的事务-目录树 -- 因此许多写权限。 这种限制只存在于 Berkeley DB 后端;FSFS 后端并没有显示这种特性。 如何完全的从版本库历史中删除一个文件? 有某些特殊情况下,你可能希望完全的删除你曾经提交文件的所有信息(或许有人意外的提交了一份保密的文 档)。但是这个操作不是很容易完成,因为 Subversion 有意被设计成决不丢失信息,修订版本是基于上一个版 本所构建的不可改变(immutable)的文件树。从版本的历史记录里删除一个 修订版本将会造成多米诺骨牌效 应,造成后继版本的混乱,还有可能使得所有的工作拷贝无效。 项目有计划在未来实现一个 svnadmin obliterate 命令,能够完成永久删除信息的任务(可以看 issue 516。)
  • 12. 现在,你只有求助于你版本库的 svnadmin dump 命令,将转储文件经过 svndumpfilter 过滤(排除错误的 路径)传递给 svnadmin load 命令,请参阅 Subversion 手册第五章的相关详细信息。 一个版本提交之后,如何修改其日志信息? 日志信息作为每个修订版本的附加属性保存在版本库,默认情况下,日志信息属性(svn:log)不能在提交后修 改。这是因为对于修订版本属性(svn:log 是其中一个)的修改会导致以前的属性永久的消失,Subversion 会防 止这种意外情况发生。但是,还是有一些方法可以修改修订版本属性。 第一种方法是让版本库管理员允许修订版本属性修改,这可以通过创建"pre-revprop-change"(更多相关细 节可以看 Subversion 手册的这个小节)。钩子"pre-revprop-change"可以在修改之前访问老的日志信息 (例如,通过发送一个邮件),所以可以以某种方式保存它(例如,通过发送邮件)。一旦开启了修订版本属性 修改,你可以通过 svn propedit 或 svn propset 的--revprop 选项修改修订版本属性,就像下面这个: $ svn propedit -r N --revprop svn:log URL $ svn propset -r N --revprop svn:log "new log message" URL 这里 N 是希望修改的日志信息的修订版本号码,而 URL 是版本库的位置。如果你从工作拷贝运行这个命令,你可 以省略 URL。 第二种方法是通过 svnadmin setlog 修改日志信息。这必须通过引用版本库的文件系统位置来执行,你不能使 用这个命令远程修改版本库。 $ svnadmin setlog REPOS_PATH -r N FILE 这里 REPOS_PATH 是版本库的位置,而 N 是你希望修改日志信息的修订版本,而 FILE 是包含新日志信息的文 件。如果"pre-revprop- change"钩子不存在(或者因为钩子脚本的原因你希望绕过),你还是可以通过-- bypass-hooks 选项实现。然而,如果你要使用这个选项,要 非常小心。你会绕过诸如变更的邮件提醒,或者保 存修订版本属性的备份系统。 怎么样向 Subversion 提交一个补丁? 首先,看一下 Hacker's Guide to Subversion。 一旦你消化了这些内容,可以在 dev 邮件列表发送一个题目有[PATCH]的邮件,并在邮件中包含你的补丁(除非 你的邮件客户端会完全处理它),不久之后就会有提交者捡起来,应用它(作出合适的格式化或内容变更),并 将其检入。 基本的过程看起来如下: $ svn co http://svn.collab.net/repos/svn/trunk subversion $ cd subversion/www [ make changes to faq.html ] $ svn diff faq.html > /tmp/foo $ Mail -s "[PATCH] FAQ updates" < /tmp/foo 当然,你的邮件应当包含补丁完成什么功能的解释,按照 Hacker's Guide to Subversion 所说的,但是你已经 知道了,因为在你 Hack 之前已经完全阅读和理解,不是吗?:)
  • 13. 我如何进行 “iplace”的导入(例如:向 Subversion 添加一个目录结构,而原先的数 据直接成为工作拷贝)? 例如,假设你希望把/etc 下的一些文件纳入版本控制: # svn mkdir file:///root/svn- repository/etc -m "Make a directory in the repository to correspond to /etc" # cd /etc # svn checkout file:///root/svn-repository/etc . # svn add apache samba alsa X11 # svn commit -m "Initial version of my config files" 这里利用了 svn checkout 的一个非立即但明显的优势:你可以从版本库直接检出一个目录到已存在的目录,这 里,我们首先在版本库创建一个目录,然后将其检出到已存在的目录/etc,将/etc 目录变成工作拷贝。一旦完 成,你可以使用普通的 svn add 命令选择文件和子目录进入版本库。 这是 svn import 的一个增强问题,它本应该能够在导入目录树时自动创建工作拷贝;可以看 issue 1328。 人们在讨论升级 Subversion 时所说的 “转储/加载(dump/load) ”是什么? Subversion 的版本库数据库模式在开发中会偶尔改变,使用 1.0 以前的 Subversion 开发版本创建的老版本库在 升级时需要如下操作。如果在发布 X 和 Y 之间的模式发生变更,则版本库管理员升级到 Y 的时候必须如下操作: 1. 关闭 svnserve、Apache 和任何可能访问版本库的东西。 2. 使用版本 X 的 svnadmin 执行 svnadmin dump /path/to/repository > dumpfile.txt 。 3. mv /path/to/repository /path/to/saved-old-repository 4. 现在升级到 Subversion Y(通过构建和安装 Y,替换 X)。 5. 使用版本 Y 的 svnadmin 执行 svnadmin create /path/to/repository。 6. 在使用版本 Y 的 svnadmin 执行 svnadmin load /path/to/repository < dumpfile.txt 。 7. 从老版本库拷贝钩子脚本等到新版本库。 8. 重启 svnserve、Apache 等等。 关于转储和加载的更多信息可以看 Subversion 手册的这个小节。 注意:大多数 Subversion 的升级不会需要转储和加载,如果某个版本需要,新版本的发布声明和 CHANGES 文 件会显著说明这一点。如果你没有看到这个说明,那么应该是没有模式变更,也就没有转储/加载的必要。 如何设置客户端通过使用 SSPI 认证的 Windows 域控制器进行认证? TortoiseSVN 有个在 Windows 下设置 Subversion 服务器的完美文档,可以看 http://tortoisesvn.net/docs/ release/TortoiseSVN_en/tsvn-serversetup.html#tsvn-serversetup-apache-5 中的 SSPI authentication 小节。 配置中比较重要的一部分是这几行: SSPIOfferBasic On 如果没有这行,支持 SSPI 的浏览器会提示用户输入凭证,但是不支持 SSPI 的客户端例如 Subversion 就不会提 示。(当前版本的 Neon - Subversion 的 HTTP 库 - 只能处理基本的认证。)因为客户端永远不会被请求凭 证,任何需要认证的操作都会失败。添加这一行告诉 mod_auth_sspi 对客户端使用基本认证,但使用 Windows 域控制器认证凭证。
  • 14. 我不喜欢 “.svn”这样的目录名字,而喜欢 “SVN”或者其他一些目录名,我该如何改变 呢? 如果可能,我们推荐你使用".svn",然而,如果你在 Windows 下使用 ASP.NET,你可能需要按这里的介绍设置 环境变量 SVN_ASP_DOT_NET_HACK。 或者你可以使用一个完全自定义的管理区域名称,我们反对这样做,因为你的工作拷贝可能无法与你的 Subversion 客户端协调工作,然而,如果你喜欢,只需要将 subversion/include/svn_wc.h 的这一行从 #define SVN_WC_ADM_DIR_NAME ".svn" 修改为(例如) #define SVN_WC_ADM_DIR_NAME "SVN" 然后重新编译客户端。 如何更改一个文件名的大小写? 这个问题在两种情况下会发生。如果你的操作系统使用的文件系统对大小写不敏感,例如 windows 系统,当你在 添加文件的时候,你可能会不小心的添加一个文件名大小写错误的文件。或者,你可能只是想改变版本库中已有 文件的大小写。 如果你是在一个大小写敏感的文件系统上工作,那基本上就不会出现这样的问题。直接将文件改成新的名字。例 如, svn mv file.java File.java 但这样的方式在 windows 这类大小写不敏感的文件系统上是不能正常运作的。在 windows 下,你只能临时地将 文件拷贝到其他地方,然后从 Subversion 中删除该文件,然后重新添加名字大小写正确的文件副本。或者更好 的办法就是对 Subversion 的 URL 执行移动操作。推荐使用操 作 URL 的方法,因为这样可以保持文件的历史日 志,而且能够立即生效。 尽管如此,这两种方式都会导致 windows 下的工作拷贝出现一些问题,因为当试图更新文件名产生冲突的文件的 时候,windows 还是会不知所措。(你可能会得到一条消息如:svn: Failed to add file 'File.java': object of the same name already exists)。一个解决这个问题的办法就是删除工作拷贝然后重新检出。如果你不想这么 做的话,那么你就必须执行上面提到的两个步骤来更新。 对于每个大小写错误的文件,执行下面的命令将会改变大小写: svn mv svn://svnserver/path/to/file.java svn://svnserver/path/to/File.java 要更新工作拷贝,你先得转到相关的目录,然后执行: svn update file.java svn update 第一步的更新会从你的工作拷贝中删除 file.java,第二步更新会添加 File.java,这样就会生成一个正确的 工作拷贝。或者如果你有很多这种问题的文件,你可以按下面的方式来更新工作拷贝: svn update * svn update 就像你看到的,添加一个大小写错误的文件在文件系统大小写不敏感的操作系统上,是需要一些小技巧来修正 的。所以最好当你第一次添加文件的时候,一次性就添加对了。为了防止类似的问题再发生,你可以创建一个 pre-commit 的钩子脚本,在其中调用文件 check-case-insensitive.pl。这个文件放在 Subversion 的源代码包 里,在 contrib/hook-scripts 目录中
  • 15. 我不能象 CVS 那样使用标签将一个分支的变更合并到主干(trunk),可以吗? 就像下面展示的,你可以不需要记住版本号就将一个分支合并到主线上面。反之亦然(在例子中并没有展示)。 下面这个例子假设在/home/repos 存在一个版本库,你希望从中创建一个名叫 bar 的、包含你即将编辑的文件 foo 的分支。 为了跟踪分支合并的历史,版本库建立了 tags/branch_traces/目录用来保存 tags。 # setup branch and tags $ svn copy file:///home/repos/trunk file:///home/repos/branches/bar_branch -m "start of bar branch" $ svn copy file:///home/repos/branches/bar_branch file:///home/repos/tags/branch_traces/bar_last_merge -m "start" # checkout branch working copy $ svn checkout file:///home/repos/branches/bar_branch wc $ cd wc # edit foo.txt file and commit $ echo "some text" >>foo.txt $ svn commit -m "edited foo" # switch to trunk and merge changes from branch $ svn switch file:///home/repos/trunk $ svn merge file:///home/repos/tags/branch_traces/bar_last_merge file:///home/repos/branches/bar_branch # Now check the file content of 'foo.txt', it should contain the changes. # commit the merge $ svn commit -m "Merge change X from bar_branch." # finally, update the trace branch to reflect the new state of things $ svn delete -m "Remove old trace branch in preparation for refresh." file:///home/repos/tags/branch_traces/bar_last_merge $ svn copy file:///home/repos/branches/bar_branch file:///home/repos/tags/branch_traces/bar_last_merge -m "Reflect merge of change X." 为什么$Revision$关键字不是我预想的那样?它替换的是文件最后修改的修订版 本,但有时候我希望它能替换文件的当前修订版本。 Subversion 每次都将整个版本库的版本号整个进行自增,所以它不能将关键词替换成你想要的数字 - 它可能不 得不在每次更新或者提交时对工作拷贝中的每个文件进行搜索或者修改。 你想要的信息(你的工作拷贝的版本号)可以通过 svnversion 命令来获取;你可以根据指定的工作拷贝的路径提 供其版本相关的信息(更多细节参考 svnversion --help)。 你可以将其组合到你的构建或发布过程中,以获取需要存放到源代码的信息。例如,在一个基于 GNU make 的构 建环境中,在你的 Makefile 中添加如下的信息: ##
  • 16. ## To use this, in yourfile.c do something like this: ## printf("this program was compiled from SVN revision %sn",SVN_REV); ## SVNDEF := -D'SVN_REV="$(shell svnversion -n .)"' CFLAGS := $(SVNDEF) ... continue with your other flags ... (注意这段代码在非 GNU 版本的 make 中无效,如果你的构建过程需要可移植,请不要使用它。) 或者使用如这些方法: ## ## on every build, record the working copy revision string ## svn_version.c: FORCE echo -n 'const char* svn_version(void) { const char* SVN_Version = "' > svn_version.c svnversion -n . >> svn_version.c echo '"; return SVN_Version; }' >> svn_version.c ## ## Then any executable that links in svn_version.o will be able ## to call the function svn_version() to get a string that ## describes exactly what revision was built. ## Windows 用户会希望使用 SubWCRev.exe,TortoiseSVN 的下载页面就有;可以用当前工作拷贝的修订版本 替换给定文件中的所有$WCREV$标签。 Subversion 是否有一个功能类似 CVS 的$Log$的关键字呢? 没有。在 CVS 中没有对应的$Log$关键字,如果你希望将日志信息输入某个特定文件,你可以使用'svn log your-file-name'或'svn log url-to-your-file'。邮件列表中有几个解释$Log$缺点的例子: “当你开 始合并分支之间的变更时,$Log$会是一个完全的梦魇。你一定会在这里得到冲突 -- 因为关键字的本性 -- 很 难简单的自动解决冲突。” 而且: Subversion 的日志信息是可以改变的,可以通过设置 svn:log 修订版本属性修改。所以在任意文件扩 展$Log:$会造成数据的过时,更新操作可能需要访问所有出现$Log:$关键字的文件,即使这些文件没有其他的 变更。 我对此并不在意,我还是期望使用它,你能实现吗? 不能,我们自己没有计划实现它,也不会接受实现这个特性的补丁。如果你希望发布包含某种变更日志的文件, 你可以在你的构建系统中跳出这个限制。 在我的工程里有一个文件,每个人都必须改变它,但是我不希望他们本地的修改被提 交,如何让'svn commit'忽略这个文件? 答案是:不要将文件纳入版本控制,而是将文件的模板纳入版本控制,例如“file.tmpl”。 然后,在初始化的‘svn checkout’之后,让你的用户(或你的构建系统)执行通过普通的操作系统复制将文件修 改为正确的文件名,文件未版本化,所以绝不会提交。并且如果你 希望,你可以将文件加入到父目录的 svn:ignore 属性中,这样它就不会在‘svn status’命令中显示‘?’。
  • 17. 当我通过 svn+ssh 来访问一个版本库的时候,我的密码没有被缓存在 ~/.subversion/auth/,我应该如何避免每次都要键入密码? ssh 拥有自己的密码短语和认证缓存模式,它的认证缓存是 Subversion 之外的,需要独立于 Subversion 设置。 OpenSSH 使用 ssh-keygen 创建密钥、通过 ssh-agent 缓存密码短语、使用 ssh-add 将密码短语添加到代 理缓存中。一个简化 ssh-agent 使用的脚本是 keychain。在 Windows 下,PuTTY 是一个流行的 ssh 客户端 选择;将 OpenSSH 密钥导入到 pageant 并缓存密码短语可以看 PuTTYgen。 设置 ssh-agent 已经超出了本文的范围,但是在 Google 中搜索“ssh-agent”可以快速得到答案,或者如果你 没有耐心,可以是看这些: http://mah.everybody.org/docs/ssh http://kimmo.suominen.com/docs/ssh/ 我的 svnserve 二进制程序不在我的用户的默认路径中,他们使用 svn+ssh,我不知 道怎样修改他们的路径来让他们运行 svnserve。 注意:这里都假设你使用了 OpenSSH。也有一些其他的 ssh 实现,大概它们也实现了这些功能,但是我们不知 道具体的方法。 你已经对修改过各种诸如.bash_profile 的登录文件,但是没有效果!那是因为当 Subversion 客户端调用 ssh 时 会忽略那些文件。但是没有必要修改 PATH;相反,你可以直接在 svnserve 命令中使用 ssh 的完全名,下面是一 个例子: 对于每个需要通过 svn+ssh 访问的用户,生成一个新的 Subversion 使用的 ssh 公钥对—不是用来登陆的。让他 们给密钥对不同的名称,例如~/.ssh/id_dsa.subversion。将密钥的公共部分添加到服务器主机的 ~/.ssh/authorized_keys 中,在开始部分包含 ssh-rsa 或 ssh-dss 以及一些幻数的行中,如下: 之前 ssh-dss AAAAB3Nblahblahblahblah 之后 command="/opt/subversion/bin/svnserve -t" ssh-dss AAAAB3Nblahblahblahblah 很明显,需要将/opt/subversion/bin/svnserve 替换为你主机上的相应值。你也会希望在命令行指明 Subversion 版本库的完全路径(通过-r 选项),节省用户使用时的输入。 command=魔法可以让远程主机的 sshd 调用 svnserve,即使你的用户尝试运行其他命令,更多细节可以看 sshd(8)的 man 页(AUTHORIZED_KEYS FILE FORMAT 部分)。 现在当你的用户运行 Subversion 客户端时,请确定他们有一个 SVN_SSH 环境变量是“指向”他们密钥对的私有 部分,通过下面的方法(Bourne Again shell): SVN_SSH="ssh -i $HOME/.ssh/id_dsa.subversion" export SVN_SSH 这个主题的详细讨论可以看这个文件。
  • 18. 我希望允许通过 svn+ssh://来访问版本库,但我很忧虑。我讨厌为每个用户分配一 个登录帐号的方法,那样我会为他们是否允许访问我的机器感到担心。 可以看对其他问题的回答中关于修改~/.ssh/authorized_keys 的部分;先不管将 svnserve 设置到路径的问 题。 我怎么才能为版本库的所有文件设置一个的属性?另外,我该如何确保每个添加到版 本库里的新文件都有这些属性? Subversion 缺省情况下不会修改文件的内容;你可以设置 svn:eol-style 或 svn:keywords 属性实现这个功 能。这让 Subversion 比 CVS 的缺省行为模式更加安全,但是安全也带来了不便。 第一个问题的答案是:设置所有已经进入版本库的文件,将会有点困难。你所要做的是在每个文件(工作拷贝文 件)上执行 svn propset,然后执行 svn commit,通过脚本应该可以帮助你做这件事。 但是对以后的文件呢?很不幸,没有在服务端自动设置提交文件属性的机制。这意味着你需要让你的用户记住在 每个 svn add 的文件上添加属性,幸运的是,有一个客户端的工具可以帮助我们做这件事,可以阅读本书的 auto-props 特性。你需要保证所有的用户配置了合适的自动化属性。 你可以写一个 pre-commit 钩子脚本来拒绝忘记在新文件添加属性的提交(例子可以看 http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/check-mime-type.pl)。然而这个方法有 点过激了,例如某人忘记了设置 svn:eol-style,那么在其他系统上用户很快就会注意到,一旦发现,可以很简单 的修正:只要设置正确的值,并提交。 注意:许多用户期望得到服务器“自动广播”运行中设置的特性,例如自动化属性设置。对此已经有了一个特性请 求(issue 1974),然而这个特性还存在争议,还没有去实现。 我如何处理编辑器路径中的空白?另外,如何定义编辑器的命令行选项? Subversion 命令行客户端会调用通过环境变量 SVN_EDITOR. 定义的编辑器,这个环境变量以及要编辑日志的 临时文件会直接传递给操作系统。 因为是要将 SVN_EDITOR 的字符串传递给系统命令行,所以如果你不加引号,编辑器名称中的空格或路径中的 空格会造成错误。 例如,在 Windows 下,如果你的编辑器在 C:Program FilesPosix Toolsbinvi,你需要这样设置环境 变量: set SVN_EDITOR="C:Program FilesPosix Toolsbinvi" 请注意没有必要在 windows 下回避引号,因为他们不是 set 命令语法的一部分。 而在 UNIX 系统中,你需要遵从你 shell 的特定方法来设定变量,例如在 bash shell 中,应该这样: SVN_EDITOR='"/usr/local/more editors/bin/xemacs"' export SVN_EDITOR 如果调用编辑器需要命令行选项,只要在 SVN_EDITOR 环境变量的编辑器名称后面输入选项,就像你平时调用 它时那样。例如,如果你的编辑器需要-nx -r 选项,可以按照下面的方式设置: 在 Windows 下: set SVN_EDITOR="C:Program FilesPosix Toolsbinvi" -nx -r 在 UNIX/bash 中: SVN_EDITOR='"/usr/local/more editors/bin/xemacs" -nx -r'
  • 19. export SVN_EDITOR 请注意 SVN_EDITOR 是 Subversion 特定的设置编辑器的环境变量,Subversion 也支持使用更普遍的 EDITOR 环境变量,但是如果你希望一些对于 Subversion 特殊的行为方式,最好还是使用 SVN_EDITOR 变 量。 如何确定版本库正在使用的 Berkeley DB 的版本? 如果它是一个活动的版本库,那么对于这个问题最简单的答案是“你安装的 Berkeley DB 的版本”。但是,如果它 是备份的或其它未知源得到的版本库,你对其的 Berkeley DB 版本一无所知,下面是你确定它的方法: 运行命令查看版本库中的高位计数文件 db/log.*中位移 12 到 16(10 进制)的两个 4 字节的整数。这里是 GNU od 的例子:“od -j12 -N8 -tx4 log.<number>”。而这里是 Mac OS X hexdump 的例子:“hexdump -s12 -n8 -x log.<number>”。第一个整数一定是幻数 0x00040988,用来注明这是 Berkeley DB 日志文件,第二 个数字是日志格式版本 - 可以使用下面的表格和 Berkeley DB 的版本匹配: Berkeley DB 版 日志格式版本 本 5 (0x00000005) 4.0 7 (0x00000007) 4.1 8 (0x00000008) 4.2 10 4.3 (0x0000000a) 11 4.4 (0x0000000b) 12 (0x0000000c) 4.5 13 4.6 (0x0000000d) 我在版本库中管理了一个网站,如何才能实现每次提交之后站点自动更新? 这个早已经解决,可以通过为版本库添加 post-commit 钩子脚本简单实现,可以读一下手册第 5 章关于钩子脚本 的内容,基本的思想是让“活动站点”变成一个普通的工作拷贝,让 post-commit 在工作拷贝中执行‘svn update’。 在实践中,有许多地方需要小心。执行提交的服务器程序(svnserve 或 apache)也是执行 post-commit 钩子 脚本的程序,这意味着 程序必须有正确的更新工作拷贝的访问许可。换句话说,运行 svnserve 或 apache 的用 户应该拥有工作拷贝 -- 或至少工作拷贝设置了合适的访问许可。 如果服务器需要更新它并不拥有的工作拷贝(例如,用户 joe 的~/public_html/区域),一个技巧是创建一个 +s 的二进制程序运行更新,因为 Unix 不允许为脚本运行+s,编译一个小的 C 程序: #include <stddef.h> #include <stdlib.h> #include <unistd.h> int main(void) { execl("/usr/local/bin/svn", "svn", "update", "/home/joe/public_html/", (const char *) NULL); return(EXIT_FAILURE); }
  • 20. ... 然后对二进制程序 chmod +s,并确认它确实被用户‘joe’所有,然后在 post-commit 钩子中,添加一行运行 二进程程序。 如果在让钩子运行时发生了问题,可以看“为什么我的钩子脚本都不能正常工作?”。 另外,你可能希望防止 apache 把工作拷贝中的.svn/目录暴露出去,在你的 httpd.conf 添加下面的内容: # Disallow browsing of Subversion working copy administrative dirs. <DirectoryMatch "^/.*/.svn/"> Order deny,allow Deny from all </DirectoryMatch> 我如何检出一个单独的文件? Subversion 不支持检出单个文件,它只支持检出目录结构。 然而,你可以使用‘svn export’来导出单个文件,这会获得文件的内容,只是不会创建版本化的工作拷贝。 如何在工作拷贝执行完添加、删除、拷贝和重命名操作之后检测这些操作? 你不需要检测,你也最好不要尝试去做这样的检测。 工作拷贝的基本设计有两个原则:(1) 你可以任意编辑文件,然后(2)使用 Subversion 客户端执行任何树目录的 改动(增加、删除、移动、拷贝)。如果这两个原则能够很好的遵守,那么客 户端就可以顺利的维护工作拷贝。 如果重命名或者其他改动是在 Subversion 之外进行的,那么 UI 就会被破坏,工作拷贝也可能发生问题。客户端 不能猜 测究竟发生了什么事。 人们有时候会遇到这样的错误,因为他们想要把版本控制变得透明化。他们诱使用户使用一份工作拷贝,然后在 稍候运行一个脚本,这个脚本会猜测用户做了 什么样的操作,然后执行相应的客户端命令。不幸的是,这样的方 式只能在短期内正常工作。‘svn status’会显示出缺失条目或者未被纳入版本控制的条目,这些条目在脚本运行的 时候会自动的被‘svn rm’或者‘svn add’。但如果发生了文件移动或者拷贝,那么你就不那么幸运了。即使脚本有 非常可靠的方法来检测这些动作,但‘svn mv’和‘svn cp’不能在这些操作已经完成的情况下运行。 总的来说,工作拷贝必须整个放置在 Subversion 的版本控制之下,Subversion 本来就不是设计成对用户透明 的。如果你想要获得这种透 明性,那么你应该建立一个 apache 服务器,然后本书附录 C 使用 的“SVNAutoversioning”特性。这将允许用户将版本库挂载成一个网络磁 盘的形式,任何对这个磁盘的修改, 都会自动提交到远程服务器上。 在 Windows 上如何将 svnserve 当作服务来运行? 对于 1.4.0 及以后的版本,你可以查看这里。 对于 1.4.0 以前的版本,svnserve 二进制本身并不可以被安装成一个 windows 服务,但有很多“service wrappers”可以完成一样的工作。例如: • SVNService Magnus Norddahl 写的一个免费的工具 • SrvAny 微软出的免费的工具 在 TortoiseSVN 手册还有一点内容关于怎么将 svnserve 安装成服务的形式。
  • 21. 如何转换我的版本库,从 BDB 到 FSFS,或者从 FSFS 到 BDB? 有三步: 1. 使用 dump/load 将旧格式转到新格式。 2. 拷贝钩子脚本。 3. 拷贝配置文件。 假设你在/svn/myrepos 目录中放置了一个版本库,使用的是 BDB,你想要将其转换成 FSFS: 1. 关闭你的服务器,这样在这个过程中数据不会发生变化。 2. 创建一个使用 fsfs 的新的版本库(这在 1.2 版本依赖就是默认的行为)。例如,svnadmin create /svn/ myreposfsfs --fs-type fsfs。 3. 将/svn/myrepos 的转储输出通过管道重定向到/svn/myreposfsfs 的加载输入上,例如,svnadmin dump /svn/myrepos -q | svnadmin load /svn/myreposfsfs。Windows 用户应该转储到一个文件 中,并且从那个文件中加载,需要分两步完成。 4. 复制在/svn/myrepos/hooks 中仍使用的钩子脚本到/svn/myreposfsfs/hooks 中。不要所有东西都拷 贝,有些模板是由 Subversion 自动生成的,可能会不一样。 5. 比较/svn/myreposfsfs/hooks 目录中 svnadmin create 命令生成的脚本模板 和/svn/myrepos/hooks 中的有什么不一样,将这些不同按需合并到你正在使用的钩子脚本中。 6. 从/svn/myrepos/conf 复制配置文件到/svn/myreposfsfs/conf 中(如果有密码文件的话,也不要忘 了)。或者你想要将配置文件中所做的修改合并到新的默认配置文件中。 7. 重命名/svn/myrepos 为/svn/myreposbdb,还有/svn/myreposfsfs 重命名为/svn/myrepos,这样 可以确保文件权限和 BDB 版本的一样。 8. 重启服务器。 一旦一切工作正常后,删除旧的版本库即可。 如果要反过来操作,即从 FSFS 移植到 BDB,只需要改变 svnadmin create 命令,将其指定为 BDB 即可。 版本库如何处理二进制文件? 当你第一次添加或者导入文件到 Subversion 中时,Subversion 会检测该文件是否是二进制文件。目 前,Subversion 的策略是 只检测文件的前 1024 个字节;如果每个字节都是 0,或者超过 15%都是非 ASCII 码 可打印字符的话,那么 Subversion 就认定该文件是二进制文 件。这种启发式方法将来可能会改进。 如果 Subversion 认定文件是二进制文件,那么这个文件就会自动添加 svn:mime-type 属性,并设置 为“application/octet-stream”。(你随时可以使用 auto-props 特性来重写这样的行为,或者使用 svn propset 手动设置属性。) Subversion 对以下的文件做普通文本处理: • 没有设置 svn:mime-type 属性的文件 • 文件的 svn:mime-type 属性值以“text/”开头 • 文件的 svn:mime-type 属性值等于“image/x-xbitmap” • 文件的 svn:mime-type 属性值等于“image/x-xpixmap” 所有其他文件都将被视为二进制文件处理,这意味着 Subversion: • 不会尝试在 svn update 或者 svn merge 操作时将远程修改合并到本地中 • 在 svn diff 中不会显示出不同 • 在 svn blame 不会显示出每一行的贡献者
  • 22. 在其他方面,Subversion 将二进制文件和其他文本文件一样对待,例如,如果你设置了 svn:keywords 或者 svn:eol-style 属性,Subversion 会在二进制文件中执行关键词替换或者行转换。 需要注意,不管是不是二进制文件,都不会影响版本库中用来存储文件变更的空间大小,也不会影响客户端和服 务端之间的通讯量。出于存储和传输考 虑,Subversion 使用的是对二进制文件和普通文本文件一致处理的 diffing 方法;这和‘svn diff’使用的 diffing 方法完全不相 关。 如何让 svn diff 仅显示被改变的文件的名字,而不是连内容也显示出来? svn diff 没有一个选项可以做到这一点,但是 • 如果你只是对修订版本号 10 和之前的版本之间的变动感兴趣,那么使用 svn log -vq -r10 完全可 以实现你的目的; • 否则,如果你是在使用 Unix 系统的话,下面这个方法对于任意范围的版本号都起作用: svn log -vq -r123:456 | egrep '^ {3}[ADMR] ' | cut -c6- | sort | uniq 1.4 版本的 svn diff 命令有一个“--summarize”的参数。 我如何使用通配符(wildcards)或者点号来一次移动多个文件? 你或许是想做这样一些事情 svn mv svn://server/trunk/stuff/* svn://server/trunk/some- other-dir 但是却失败了 svn: Path 'svn://server/trunk/stuff/*' does not exist in revision 123 ... 或者还有其他一些看起来不可理解的错误信息。 简而言之,很不幸:Subversion 没有内置这样的方法来进行这样一种操作;许多其他的命令,例如 mv,不会接 受任意数目的参数...在任何情况下,Subversion 都不会扩展如 shell 所支持的“*”号通配符。 如果你刚好有一个工作拷贝包含了和目标目录一摸一样的源文件,那么你可以使用你的 shell 中的通配符特性来 完成移动文件的目的,例如(在 bash 下): for i in stuff/*; do svn mv $i some-other-dir; done svn ci -m "moved all the stuff into some other dir" 在任何情况下,你都可以将源文件的名字拼成一个列表,然后使用“svn mv”命令对列表中的每一项都执行同样的 指令,就像下面所做的一样: s=svn://server/trunk/stuff/ svn ls "$s" | while read f do svn mv "$s/$f" svn://server/trunk/some-other-dir -m "Moved just one file" done 但是需要注意的是,这样会造成每个文件都执行一次提交动作,这和上面的方法(使用工作拷贝)不同,上面的 方法总共就会执行一次提交动作。 有一个程序叫“svnmucc”或者“mucc”可以解决你的这个问题,不过它依赖于你的 Subversion 版本号,它的源 代码已经发布在 Subversion 中了(对于 Subversion 1.4 以及更早的版本,这个工具的源文件放置在/contrib/ client-side/mucc/mucc.c,对于 1.5 及之后的版本,则在/contrib/client-side/svnmucc/svnmucc.c 可以找 到)。
  • 23. 注意:随着 1.5 版本的正式发布,Subversion 事实上允许你一次性同时“cp”和“mv”多个文件。 我如何用 Subversion 维护一个由第三方不断修正版本的软件呢?(一个"供方分 支")? 人们通常希望使用 Subversion 去跟踪他们的变化的第三方代码,甚至从第三的代码进行升级,换句话说,他们 想维护他们自己的一个分支,与此同时仍然希望从上游的代码并入新的发布。这通常被叫做供方分支(这个术语 早于 Subversion),Subversion 维护这种分支的技术可以看这个描述。 如果供方代码是远程的主机上的 Subversion 版本库,你可以使用 Piston 来管理你的供方代码拷贝。 最后,如果使用 svn_load_dirs.pl 花太多时间的话,或者你正在寻找一个偷懒的方案,则可以参考 Jon Stevens 的渐进介绍如何使用 Subversion 供方分支。这种解决方案在你拷贝新的代码去覆盖旧代码的时候并不 能利用 Subversion 后端的节省空间特性换;在这种解决方案中,每一份导入的供方代码都会是一个新的拷贝, 相同的文件不会节省存储空间。 疑难解答: 我的版本库经常看起来卡住了,一直报一个需要重新恢复(DB_RUNRECOVERY)的 错误,怎么会导致这个问题? 版本库使用的 Berkeley DB 数据库很容易受到破坏。如果进程退出时没有正常关闭数据库,那么数据库就处在非 正常状态中。常见的原因可能是: • 进程遇到访问权限问题而退出时 • 进程崩溃或段错误 • 进程被强制杀死 • 磁盘空间用尽 多数情况下,你可以执行"svnadmin recover",这个命令可以将版本库回退到上一个正常状态,详细解释请见 bdb-recovery。注意,当频繁的 checkout 和 update 且磁盘空间用尽的时候,可能导致版本库处于无法恢复的 状态(所以请多做备份)。 进程崩溃,被杀死以及磁盘空间用尽都是极端情况。访问权限问题可能是更常见的原因:当一个进程访问版本库 且改变了版本库的所有者或访问权限,那么另一个访问这个版本库的进程可能被阻塞在访问权限上。 避免这种情况出现的最好办法是正确设置你的版本库的所有者和权限。查看更多信息。 每次我想访问我的版本库,进程就会挂起。我的版本库坏掉了吗? 你的版本库没有坏掉,数据也没有丢失。当你的进程直接访问版本库(mod_dav_svn、svnlook、svnadmin, 或通过 ‘file://’)的时候,进程将直接通过 Berkeley DB 来访问版本库。Berkekey DB 包含日志系统,也就是 说所有的操作在执行前都被记录在日志中。当你的进程崩溃(Control-C,或段错误),遗留下文件锁,它记录了 所有未完成操 作的信息。此时所有试图访问数据库的进程将因为要访问文件锁而被挂起。要想解除文件锁,你可 以调用 Berkeley DB 来完成所有未完成的操作或者回退到前一个正常状态。 警告:当一个进程正在访问版本库,而你又试图恢复版本库的时候,版本库可能会严重损坏。 在你恢复数据库之前,请确保没有其他进程在访问版本库(关闭 Apache, 去掉'svn'的执行权限) 。确认你是以数 据库所有者及管理员的用户进行操作的,而不是 root 用户。否则数据库将只能被 root 用户访问,而其他用户 (你自己或 Apache)将无 法对数据库进行操作。同时,还要确保 umask 被正确设置,否则其他隶属与可以访 问该数据库的组的用户可能无法对数据库进行操作。
  • 24. 执行: svnadmin recover /path/to/repos 当命令执行完毕, 检查版本库 db 目录的访问权限 有时"svnadmin recover"会失败,错误信息如下: Repository lock acquired. Please wait; recovering the repository may take some time... svnadmin: DB_RUNRECOVERY: Fatal error, run database recovery svnadmin: bdb: Recovery function for LSN 175 7066018 failed on backward pass svnadmin: bdb: PANIC: No such file or directory svnadmin: bdb: PANIC: fatal region error detected; run recovery 或者: Repository lock acquired. Please wait; recovering the repository may take some time... svn: DB_RUNRECOVERY: Fatal error, run database recovery svn: bdb: DB_ENV->log_flush: LSN of 115/802071 past current end-of-log of 115/731460 svn: bdb: Database environment corrupt; the wrong log files may have been removed or incompatible database files imported from another environment [...] svn: bdb: changes: unable to flush page: 0 svn: bdb: txn_checkpoint: failed to flush the buffer cache Invalid argument svn: bdb: PANIC: Invalid argument svn: bdb: PANIC: fatal region error detected; run recovery svn: bdb: PANIC: fatal region error detected; run recovery [...] 这种情况下可以试试 Berkeley DB 的工具 db_recover (参见 db_recover 文档).这个命令通常在 Berkeley DB 安装目录的子目录"bin/"中, 例如你从源代码安装的 Berkeley DB,命令可能是 /usr/local/BerkeleyDB.4.2/ bin/db_recover;或在某些系统中预安装的 Berkeley DB,可能是 /usr/bin/db_recover.如果你的系统中安装 了多个版本的 Berkeley DB,请确保使用匹配版本库的 Berkeley DB 版本 执行 db_recover,附带参数"-c" ("灾难恢复").你还可以附带 "-v"来看到执行的详细信息, "-h"指定被 恢复的数据库。例如: db_recover -c -v -h /path/to/repos/db 用版本库的拥有者的帐号执行这个命令,同时,请绝对确保没有其他进程在 访问版本库。(例如,关闭 svnserve 或)。 我的版本库一直报告错误"Cannot allocate memory",我该怎么办? 如果你通过 http://来访问版本库,"Cannot allocate memory"应该出现在 httpd 服务器的日志中,像下 面这样: [Wed Apr 07 04:26:10 2004] [error] [client 212.151.130.227] (20014) Error string not specified yet: Berkeley DB error while opening 'strings' table for filesystem /usr/local/svn/repositories/svn/db: Cannot allocate memory [Wed Apr 07 04:26:10 2004] [error] [client 212.151.130.227] Could not fetch resource information. [500, #0] [Wed Apr 07 04:26:10 2004] [error] [client 212.151.130.227] Could not open the requested SVN filesystem [500, #160029]
  • 25. [Wed Apr 07 04:26:10 2004] [error] [client 212.151.130.227] (17) File exists: Could not open the requested SVN filesystem [500, #160029] 这通常表示 Berkeley DB 版本库用光了所有数据库锁(FSFS 版本库不会出现这种情况)。通常的运行过程中不 应该出现这种情况,如果确实出现了,解决办法是用本文中描述的方法来恢复数据库。如果这种情况时常发生, 你很可能应该提高 db/DB_CONFIG 文件中锁设置(set_lk_max_locks、set_lk_max_lockers 和 set_lk_max_objects)的默认值。改变已存在的版本库的 DB_CONFIG 配置后,记得恢复数据库。 每当我试图运行一个 svn 命令时,都会提示我的工作拷贝已经被锁定了,是我的工作 拷贝坏掉了吗? 你的工作拷贝没有坏掉,数据也没有丢失。Subversion 的工作拷贝是一个日志系统,所有的操作在执行之前都 被记录在日志中。如果 svc 客户端程序被 强制中止(段错误或杀进程,不包括 Control-C),会有多个文件锁 遗留下来,记录了未完成的操作。('svn status'命令会在被锁定的目录后显示'L'。)其他试图访问工作拷 贝的进程看到这些锁后会返回操作失败。想解锁你的工作拷贝,需要让 svn 客户端完 成未完的操作。执行: svn cleanup working-copy 我试图去提交,但是 Subversion 说我的工作拷贝是过时的? 三种情况下会出现这个问题 提交失败导致了你的工作拷贝被破环。 在你提交时,新版本被添加到服务器上,然后你的客户端执行提交后的管理任务(包括刷新本地拷贝)。在第二 个操作之前,你的提交处在一个“过期”的状态之中。导致这种情况发生的原因有,(极少数情况下)数据库一端 出现了问题,(大多数情况下)网络在错误的时间中断了。 这 时,很可能你的提交已经成功了。你可以执行"svn log -rHEAD"来查看提交是否真的成功了。如果成功了, 执行“svn revert”,回退本地修改,然后执行“svn update”来取回你已经提交的修改。(注意,“svn update”能更新你的本地拷贝,而 revert 不能。) 版本混杂。 提交的时候,在客户端的工作拷贝中,只有此次提交涉及的节点会被更新,而不是所有节点。这意味着, 你最后 一次提交决定你的工作拷贝中了文件和目录的版本号,他们可能不是同一版本。对于像修改目录属性等特定操 作,如果版本库中有更新的版本,你的提交会被 拒绝,以防止数据丢失。详细请见版本混杂的局限在使用 Subversion 做版本控制中。 执行'svn update'可以解决这个问题。 你的版本可能确实是过时的 — 即在你提交的时候,有人基于你的上一次改动又作了更新。执行'svn update'来解 决这个问题。 我为项目贡献了一个补丁,而这个补丁添加了一个新文件,现在 svn update 不能工 作了。 如果要往补丁里加入新文件,你可能得使用 svn add 命令,这样 svn diff 命令才会将新文件包含在补丁里面。如 果你的补丁已经提交到代码库里头了,然后你运行 svn update,这个时候你可能会收到错误提示:“svn: Failed to add file ‘my.new.file’。object of the same name already exists”(不能增加“my.new.file”, 同名文件已经存在)。 之所以会产生这个错误是因为你的工作拷贝中已经有这个文件了。解决这个问题的步骤如下: 1. 运行 svn revert 命令,把原先标记为添加的修改撤销掉。 2. 删除文件或者将其移动到工作拷贝外的其他位置。
  • 26. 3. 现在你应该可以运行 svn update 命令了。 你可能需要把版本库中的新文件和你的本地的文件做一下比较。 我编译了 Subversion 的发行版,当我试图 check out 的时候,我得到一个错 误"Unrecognized URL scheme."这时怎么回事呢? Subversion 使用了插件系统来访问版本库。现在支持三个插件:ra_local 支持访问本地版本库,ra_dav 支持通 过 WebDAV 访问 版本库,ra_svn 支持通过 svnserver 服务器访问远程或本地的版本库。当你执行 Subversion 的操作时,会根据 URL scheme 来决定加载哪一个插件。以`file://'开头的 URL 会加载 ra_local,`http://'开 头的 URL 会加载 ra_dav。 你看到的错误是说无法找到正确的插件。发生这个问题,通常是因为你将 Subversion 的库文件编译成动态库 后,却没有执行'make install'。或者虽然你执行了'make install',但是操作系统还是找不到 Subversion 的动 态库所在的路径。在 Linux 系统中,你可以把相应的路径加入到/etc /ld.so.conf 中,然后运行 ldconfig。如果 你不想这么作,又或者你没有 root 权限,你可以在 LD_LIBRARY_PATH 中指定相应 的路径。 当我查找或打开一个版本库时出现错误,但是我知道我版本库 URL 是正确的,哪里出 错了? 参考这个 FAQ 条目。 当我运行`configure'命令时,出现一些错误 subs-1.sed line 38: Unterminated `s' command。 这是怎么回事? 可能你系统里的/usr/local/bin/apr-config 和/usr/local/bin/apu-config 太旧了。删了它们,更新 apr/和 apr- util/,使其和你编译的版本保持一致,再重新编译。 我在 Windows 下用 MSVC++6.0 构建 Subversion 时候有些麻烦,我该怎么办? 可能你需要最新版本的 platform SDK,VC++ 6.0 带的 SDK 太旧了。 我如何在 file:格式的 URL 中指定 Windows 盘符? 像这样: svn import file:///d:/some/path/to/repos/on/d/drive 更多细节请见 Subversion 书中的版本库 URL。 VS.NET/ASP.NET 似乎不能处理".svn"目录名。我该怎么办? VS.Net 有一个 ASP.Net 子系统,它使用 WebDAV 来通过 IIS 来远程发布。这个子系统剔除了所有以"."开头的 目录。在你试图远程发布 你的工作目录的时候,".svn"将导致问题。错误信息类似"unable to read project information"。 要想绕过这个问题,设置环境变量 SVN_ASP_DOT_NET_HACK 为任意值 — 这将告诉 Windows clients 在你 的工作拷贝中使用"_svn"作为目录名。参见 Subversion 1.3 发布说明的相关章节来取得更多信息,参见这个问 题来用其他方法配置管理目录名。 我在通过网络对 Subersion 版本库进行写操作的时候有些麻烦。 例如,有用户反映,通过本地协议访问的,导入功能正常工作: $ mkdir test
  • 27. $ touch test/testfile $ svn import test file:///var/svn/test -m "Initial import" Adding test/testfile Transmitting file data . Committed revision 1. 但如果从远程访问的话就出错了: $ svn import http://svn.sabi.net/test testfile -m "import" nicholas's password: xxxxxxx svn_error: #21110 : <Activity not found> The specified activity does not exist. 我们曾经遇到过这样的问题,当 httpd 进程对 REPOS/dav/目录没有可写权限的时候会发生。你需要检查一下相 关的权限问题,确保 Apache 能够往 dav/目录中写入东西。(当然还有 db/目录)。 在 Windows XP 下,Subversion 服务器有时候会发布一些错误数据,真的是这样 吗? 你需要安装 Windows XP 的 SP1 补丁。你可以在下面这里找到所有相关的信息: • http://support.microsoft.com/default.aspx?scid=kb;EN-US;q317949 在 Subversion 服务器和客户端之间进行交互时,跟踪网络的最好方法是什么? 可以参考 hacking.html#net-trace。 为什么 svn revert 要求有一个明确的目标?为什么它默认不是递归执行的呢?这与所 有其他的子命令都不同。 简而言之,这是为你好。 Subversion 对保护你的数据非常重视,不只是你已经版本化的数据。你对已经版本控制的文件所做的修改,或者 你即将添加到版本库中的文件,都必须小心对待。 使用 svn revert 命令需要非常明确地指定目标—即使目标是‘.’—就是其中一个方面。这个要求(同样对于-- recursive (-R)标记,如果你真的需要递归执行某个操作,你也要这样做)是为了让你清楚的知道你要做的事 情,因为一旦你执行了撤销工作拷贝修改的命令,所有本地的修改都会永远消失。 当我启动 Apache 时,mod_dav_svn 报告"bad database version",它发现的 是 db-3.X,而不是 db-4.X。 你的 apr-util 链接的是 DB-3,而 svn 链接的是 DB-4。不幸的是,DB 符号并不是不相同的。当 mod_dav_svn 被加载入 Apace 的进程空间的时候,他会使用 apr-util 的 DB-3 库来解析符号。 解决办法就是确保 apr-util 是在 DB-4 下编译的。你可以在编译的时候指定特定的开关为 apr-util 的配置或者 apache 的配置:“--with-dbm=db4 --with-berkeley-db=/the/db/prefix”。 在 Red Hat 9 中,我得到一个"Function not implemented"错误,一切都停止工 作。我该如何修正它呢? 这确实不是 Subversion 的问题,但经常会影响 Subversion 用户。
  • 28. 随 Red Hat 9 还有 Fedora 发行的 Berkeley DB 库依赖于对 NPTL 的内核支持(本地 Posix 线程库)。 Red Hat 提供的内核对这方面有内置的支持,但如果你是自己编译的内核,那么你可能不会有 NPTL 的支持。如 果是这个原因的话,那么你可能会看到如下的错误: svn: Berkeley DB error svn: Berkeley DB error while creating environment for filesystem tester/db: Function not implemented 这个问题可以按照下面的方法解决: • 根据你使用的内核重新编译 Berkeley DB。 • 使用 Red Hat 9 内核。 • 使用 NPTL 内核补丁。 • 使用内置了 NPTL 支持的比较新的内核版本(2.5.x)。 • 检查 LD_ASSUME_KERNEL 环境变量是否已经设置为了 2.2.5,如果是的话,在重新启动 Subversion(Apache)之前删除此环境变量。(通常只有当你在 Red Hat 9 上面运行 Wine 或者 Winex 才需要设置这个环境变量) 要使用 NPTL 版本的 Berkeley DB,你还需要使用支持 NPTL 的 glibc 库,很可能是 i686 版本。参考 http://svn.haxx.se/users/archive-2004-03/0488.shtml。 为什么文件通过 Apache(ra_dav)被提交和导入时,SVN 的日志说 “(no author)”? 如果你在 Apache 上开启了匿名用户的写权限的时候,Apache 服务器就不会向 svn 客户端询问用户名,而是直 接不经过验证就允许执行写操作。因为 Subversion 不知道谁做了这些操作,日志中这些操作信息就变成下面这 样了: $ svn log ------------------------------------------------------------------------ rev 24: (no author) | 2003-07-29 19:28:35 +0200 (Tue, 29 Jul 2003) 关于如何配置 Apache 的访问权限,参考 Subversion 书籍("Networking a Repository")。 我在 Windows 平台上偶尔会得到一个"Access Denied"错误,它的发生好像没有什 么规律,为什么呢? 这可能是由于一些监听文件系统变化的 windows 服务(如杀毒软件,索引服务,COM+事件通知服务)。这不属 于 Subversion 的 Bug,所以我们很难修正这个问题。关于这种情况的调查说明可以在这里找到。在 7598 版本 中,对这个问题做了改进,对于大多数人来说,应该会降低这种情况出现的几率。如果你使用的是较早的版本, 请更新到最新的发行版。 在 FreeBSD 上,某些操作(尤其是 svnadmin create)有时候会被挂起。为什么? 这通常是由于系统中某些资源不足的缘故造成的。你很可能需要配置一下系统,使其能够从源那里获取足够的资 源,如硬盘还有网络中断。查阅你的系统说明手册,找到 random(4)还有 rndcontrol(8)这几节,看如何修改。
  • 29. 我可以从一个 WEB 浏览器上查看我的版本库,但是在执行'svn checkout' 时发生一 个错误:"301 Moved Permanently"。那个地方出错了? 这意味着你的 httpd.conf 配置有问题,通常情况下,当你设置的 Subversion 虚拟目录同时存在两种寻址方式的 时候会出现这样的错误。 例如,当你将版本库放到/www/foo 目录下,但是你又同时设置了你的版本库的根目录为/www,那么你就麻烦 了。当有人请求 一个/www/foo/bar 文件的时候,apache 根本不会知道,对方真正想要寻找的文件,是在根目 录里下的/foo/bar,还是通过调用 mod_dav_svn 模块从/www/foo 版本库中去把/bar 文件给取回来,通常 Apache 的处理行为是采取前者的方式,因此就会出现“永久转移 ”这样的错误了。 解决这个问题的办法就是确认你的版本库路径不会有重叠,或者存在其他网络共享可访问的路径里面。 出现这个问题还有一个可能的原因,就是在网站根目录存在一个和版本库的 URL 同名的文件(文件夹)。例如, 假设你的 WEB 服务器的根目录设置在 /var/www,你的 Subversion 版本库被放置在/home/svn/repo 目录 下,然后你在 Apache 下将该版本库的 URL 配置成 http://localhost/myrepo。如果你这时又在/var/www 下 创建了一个 myrepo 的目录,那么同样会产生 301 的错误。 为什么 HTTP 摘要认证(HTTP Digest auth)不能正常工作? 这个问题很可能是因为 Apache 服务器的一个已知的 bug(存在于 2.0.48 或者更早期的版本),你可以在 http://nagoya.apache.org/bugzilla/show_bug.cgi?id=25040 找到相应的补丁。你也可以在 http://subversion.tigris.org/issues/show_bug.cgi?id=1608 上看有没有和你说的情况类似的已反馈的 bug。 我在 AIX 上面编译 xls 的时候出现编译错误,为什么呢? 在环境变量 CFLAGS 中加入-qlanglvl=extended 作为配置参数,这会使到编译 xls 的时候更加灵活,这样应该 不会再出现编译错误了。更详细的信息请参阅 http://svn.haxx.se/dev/archive-2004-01/0922.shtml 及相 关的文章。 我使用非递归的方式(使用 -N 参数)检出一个目录后,现在我想让某些特定的子目 录再 “出现 ”,但 svn up subdir 命令不能正常使用。 参考 issue 695. 当前的 svn checkout -N 命令的实现非常糟糕。它会造成工作拷贝某些条目缺失,但它本身又 没有意识到已经出现了不完整性的问题。很显然,很多的 CVS 用户已经对这种使用方式习以为常了,但是 Subversion 的用户还并不习惯。目前还没有好的办法解决这个问题,只能让你自己改变操作的流程:先试着检出 单独的子目录,然后再手动嵌入到你的工作拷贝中。 我试着在 win32 平台的 Apache 上使用 mod_dav_svn 模块,但是却提示我模块未 找到的错误,但是 mod_dav_svn.so 这个文件明明就放在Apachemodules 目 录中。 这个错误信息在这里有点误导人。通常这样的错误是因为 Apache 无法正确加载 mod_dav_svn.so 模块所依赖 的模块。如果当前 Apache 是以服务的形式运行的,那么它的 path 环境变量和普通用户的并不相同。请确认 libdb4*.dll、intl3_svn.dll、 libeay32.dll 还有 ssleay32.dll 都可以在Apachebin 或者Apachemodules 目录中找到。如果没有找到,你可以从 Subversion 的安装目录下拷贝一份。 如果这样还解决不了问题的话,那么你可以使用类似 Dependency Walker 这样的工具来查看 mod_dav_svn.so 库的依赖性,看是否还有尚未解决的依赖性问题存在。
  • 30. 为什么我的钩子脚本都不能正常工作? 这些钩子脚本应该会触发外部程序的,但是这个触发过程似乎并没有执行。 当 Subversion 调用一个钩子脚本时,它会将所有环境变量都清除干净,包括 unix 下的$Path 和 windows 下 的%Path%变量,因此,如果你的脚本要访问外部程序的话你就必须指定好外部程序的完整路径。 调试技巧: 如果你正在运行 Linux 或者 Unix 操作系统,试一下按照下面的步骤手动运行一下脚本: 1. 使 用 "su"、"sudo"或者类似的命令来切换到一般情况下可能会运行该脚本的用户。如果你运行的是 Apache 服务器的话,那么这个用户通常是 httpd 或者 www-data。如果你运行 svnserve 的话,那么 很可能是使用 svn 的帐户来运行该脚本。这样切换用户之后来运行脚本的好处就是不会再有脚本 运行权 限错误的问题出现。 2. 使用 env 程序清除所有环境变量然后再运行该脚本,如下所示: $ env - ./post-commit /var/lib/svn-repos 1234 注意到传递给 env 程序的第一个参数是一个横杠,这 样可以保证环境变量为空。 3. 查看控制台有没有输出错误信息。 为什么我的--diff-cmd 会有关于 ‘-u’的报错,我想用--extensions 去覆盖它,但是 不起作用。 当使用一个外部的 diff 命令时,Subversion 会生成一个非常复杂的命令行。第一个参数就是具体的--diff- cmd,然后就是具体的 --extensions (尽管使用空白的 --符号时会忽略扩展),或者如果没有指定-- extensions 或者--extensions 为空的话,就加上‘-u’参数。第三和第四个参 数,Subversion 会传递一个“-L”还 有第一个文件的标签(例如,“"project_issues.html (revision 11209)”)。第五个和第六个就是另一个“-L”和 第二个文件的标签。第七和第八个参数分别是第一个和第二个文件的名称(例 如,“.svn/text- base/project_issues.html.svn-base”和“.svn/tmp /project_issues.html.tmp”)。 如果你指定的 diff 命令不支持这些参数的话,你可能需要创建一个简单的封装脚本来忽略这些参数,然后将最后 的你需要的文件的路径参数传递给 diff 命令。 警告:Subversion 并不希望外部的 diff 工具会改变它接收到的文件,否则可能会破坏当前工作拷贝。 更多信息请参考 issue #2044. 啊呀,我刚刚发现我的 Subversion 客户端居然把我的密码以明文的方式缓存在本地 硬盘中!!! 冷静一下,深呼吸。 在 windows 2000 及之后的版本上,svn 1.2 之后的版本都使用标准的 windows API 来加密数据,所以只有用 户自己能够解密出缓存的密码来。 在 Mac OS X, svn 1.4 以后的版本使用系统的 keychain 功能来加密以及存储 svn 的密码。 Subversion 1.6 会为 UNIX/Linux 处理这个问题,对于 GNOME Keyring 和 KWallet 的支持已经实现,都可以 方便的在磁盘上存储加密的密码。这些程序可以在运行中的或编译中添加。如果没有,客户端会使用明文 缓存密 码,但是它如果以明文存储我们会首先询问是否允许。