目录
file://
的URL中指定一个Windows驱动器盘符?
301 Moved Permanently
错误。
在安装和使用Subversion的过程中会有许多问题,有一些在你更加理解Subversion之后会立刻解决,而有一些会引起麻烦,因为你已经习惯于其它版本控制系统的工作方式。也有一些其它的问题不能解决是因为Subversion在一些操作系统上有bug(考虑到Subversion运行系统的广泛性,没有遇到更多已经是一件让人吃惊的事情了)。
下面的列表是从Subversion多年使用过程中编辑出来的,如果你没有在这里发现问题,可以在Subversion网站上察看最新版本的FAQ。如果你还是有问题,可以发送包含你遇到问题详细描述的邮件到<[email protected]>
。
[46]
这里是Subversion的FAQ最流行的问题。
你的版本库和数据都没有损坏,如果你的进程直接访问版本库(mod_dav_svn、svnlook、svnadmin或者你通过file://
的URL访问),然后它会使用Berkeley DB来访问你的数据。Berkeley DB是一个日志系统,意味着在做一件事之前会记录下来所有的事情,如果你的进程被中断(例如一个终止信号或段错误),这样就会留下一个锁文件,还有一个描述未完成业务的日志文件。任何其它尝试访问数据库的进程会挂起,等待锁文件消失。为了唤醒你的版本库,你需要询问Berkeley DB是否结束工作,或者是恢复数据库到前一个已知的稳定状态。
确定你使用数据库的拥有者和管理者用户来运行这个命令,而不是root或是其它会在db目录产生root拥有文件的用户,这些文件不可以由管理数据库的非root用户打开,通常是你或你的Apache进程。也要确定在恢复时有正确的umask设置,因为如果失败会把允许访问版本库的用户组锁在外面。
简单的运行:
$ svnadmin recover /path/to/repos
一旦这个命令完成,检查版本库db/
目录的访问限制。
Subversion的工作拷贝,就像Berkeley DB使用日志机制来执行所有的操作,也就是它会在事情发生前记录所有的操作。如果svn在一个动作中被中断,就会留下一个或多个锁文件以及相关的描述未完成动作的日志文件。(svn status会在锁定的目录前面显示一个L
。)
任何其它尝试访问工作拷贝的进程会在看到锁定后会提示失败,为了唤醒工作拷贝,你需要告诉客户端完成工作,做为修正,在你的工作拷贝顶级目录运行这个命令:
$ svn cleanup
见“每当我尝试访问版本库,我的Subversion客户端挂起。”一节。
你也许也遇到了一个版本库访问权限问题,见“支持多种版本库访问方法”一节。
见版本库的URL。
如果本地访问的导入工作正常:
$ 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 test http://svn.red-bean.com/test -m "Initial import" harry's password: xxxxxxx svn_error: … The specified activity does not exist.
如果REPOS/dav/
目录对httpd进程不是可写的我们会看这些,检查权限来确定Apache的httpd进程可以写访问dav/
目录(当然也同样对于db/
目录)。
你需要安装Windows XP Service Pack 1来修正操作系统的TCP/IP堆栈bug,你可以查看http://support.microsoft.com/default.aspx?scid=kb;EN-US;q317949
来得到这个Service Pack的所有信息。
使用Ethereal来偷听对话:
如下的指导针对Ethereal的图形化版本,不是应用在命令行版本(二进制文件通常叫做tethereal)。
打开Capture菜单,选择Start。
Filter的port输入80,关闭promiscuous模式。
运行Subversion客户端。
点击Stop,你现在已经捕捉了,它看起来像是巨大的行列表。
点击Protocol列来排序。
然后,点击第一个相关的TCP行来选择它。
右键,选择Follow TCP Stream,你会看到Subversion客户端的HTTP对话的请求/响应对。
另一种选择,你可以在客户端的servers
运行配置文件中设置一个参数,来允许neon调试信息的出现,neon-debug得数字值是头文件ne_utils.h
中NE_DBG_*
值的组合,设置neon-debug-mask
变量为130(例如NE_DBG_HTTP + NE_DBG_HTTPBODY
)会导致显示HTTP数据。
你或许也会希望在网络跟踪时关掉压缩,可以通过设置同一个文件的http-compression
参数。
Subversion使用一个插件系统来允许访问版本库,当前有三种这样的插件:ra_local允许访问本地版本库,ra_dav允许通过WebDAV访问,而ra_svn允许通过svnserve服务器本地或远程访问。当你尝试执行一个Subversion操作,程序会根据URL模式动态的加载一个插件,file://
的URL会加载ra_local,而http://
的URL会尝试ra_dav。
你看到的错误意味着动态链接器/加载器不能发现需要加载的插件,这通常是因为你使用共享库编译Subversion,然后尝试在没有首先运行make
install时运行它。另一个可能的原因是你运行了make install,但是库安装的位置动态链接器/加载器不能识别。在Linux,你可以通过在库目录添加/etc/ld.so.conf
并运行ldconfig来允许链接器/加载器找到这些库。如果你不希望这样做,或者是你没有root权限,你可以直接在LD_LIBRARY_PATH环境变量中指定库目录。
一句话:它有自己的好处。
Subversion把保护你的数据作为非常高的优先级,对于已经版本化的文件的修改,和预定要添加到版本控制的文件,必须小心对待。
让svn revert命令需要一个明确的目标—即使目标只是“.”—是实现这个目的的一个方法。这个要求(同样的还有要求使用--recursive
来实现递归的行为)是为了让你清楚自己所做的事情,因为一旦你的文件被恢复,你的本地修改就会永远消失。
你的apr-util链接了DB-3,而svn链接了DB-4,很不幸,DB对象并没有区别。当mod_dav_svn加载到Apache的处理空间,它无法解析针对apr-util的DB-3的对象名称。
解决方案是确定apr-util针对DB-4编译,你可以通过指定apr-util或Apache的选项来完成这一点:"--with-dbm=db4 --with-berkeley-db=/the/db/prefix"。
这不是Subversion的问题,但是经常影响Subversion用户。
RedHat 9和Fedora分发版本中包括了Berkeley DB库,依赖于为NPTL(the Native Posix Threads Library)内核支持,RedHat得内核提供了内置的支持,但是如果你编译了你的内核,你或许不再有NPTL的支持,所以这种情况下你会看到这样的错误:
svn: Berkeley DB error svn: Berkeley DB error while creating environment for filesystem tester/db: Function not implemented
可以用以下的任意一种方法修正这个问题:
重新为你使用的内核编译db4。
使用RedHat 9的内核。
为你使用的内核应用NPTL补丁。
使用最近的(2.5.x)包括NPTL支持的内核。
检查环境变量LD_ASSUME_KERNEL
是否设置为2.2.5,如果是,在运行Subversion(Apache)之前取消设置。(在RedHat 9运行Wine或Winex时你通常会设置这个变量)
如果你允许通过Apache的匿名写访问版本库,Apache从不会要求客户端的用户名,而且在写操作中没有认证,因此Subversion对于谁做的操作一无所知,这导致了这样的日志:
$ svn log ------------------------------------------------------------------------ rev 24: (no author) | 2003-07-29 19:28:35 +0200 (Tue, 29 Jul 2003) …
阅读如何添加认证在第 6 章 配置服务器。
这看起来是因为不同的监控文件系统变化(杀毒软件、目录服务和COM+事件通知服务)的Windows服务。这不是Subversion的bug,让修正变得很困难。当前状态的研究总结在http://www.contactor.se/~dast/svn/archive-2003-10/0136.shtml
,一个用来减少大多数人发生概率的工作在修订版本7598已经实现。
这通常是因为系统缺乏可用的信息量,Subversion一次次询问APR产生随机数来创建UUID,特定操作系统会阻止高质量的随机性,你可能需要配置系统从硬盘和网络中断等资源中收集信息,咨询你的系统管理员,明确random(4)和rndcontrol(8)怎样影响这些变化。另一个工作区让APR根据/dev/urandom
而不是/dev/random
编译。
这意味着你的httpd.conf错误的配置,通常这个错误发生在你定义Subversion虚拟“location”时使之同时存在于两个不同的范围。
例如,如果你已经以<Location /www/foo>
导出了一个版本库,但是你也已经设置了DocumentRoot
为/www
,然后你会陷入麻烦,当请求要得到/www/foo/bar
,Apache不知道是去找一个DocumentRoot
下的真实文件/foo/bar
还是询问mod_dav_svn从/www/foo
版本库得到一个文件/bar
,通常是前一种情况发生作用,因此得到"Moved Permanently"错误。
解决方案是确定你的版本库的<Location>
没有重叠,或者是没有存在于已经作为普通web共享暴露的目录。
Subversion的一个好的特性是版本库理解拷贝和重命名,并且保留历史联系。举个例子,如果你拷贝/trunk
到/branches/mybranch
,然后版本库理解为在分支的每个文件都在trunk有个“前辈”。运行svn log --verbose会显示历史拷贝,所以你可以看到重命名:
r7932 | joe | 2003-12-03 17:54:02 -0600 (Wed, 03 Dec 2003) | 1 line Changed paths: A /branches/mybranch (from /trunk:7931)
很不幸,当版本库意识到拷贝和重命名,版本1.0的几乎所有的svn客户端子命令还没有意识到。svn diff、svn
merge和svn cat应该理解这些重命名,但是它们没有。它们是1.0之后的特性,举个例子,如果你询问svn diff比较两个早期版本的/branches/mybranch/foo.c
,这个命令不会自动理解为实际上我们是要比较两个版本的/trunk/foo.c
,因为这个重命名。相反,你会看到一个错误说这个分支路径在早期的修订版本并不存在。
解决所有此类问题的方法是你自己的调查,也就是:你需要知道所有的重命名路径,自己使用svn log -v去发现,然后明确地告诉svn客户端,例如,我们不应该运行
$ svn diff -r 1000:2000 http://host/repos/branches/mybranch/foo.c svn: Filesystem has no item svn: '/branches/mybranch/foo.c' not found in the repository at revision 1000
...而会运行
$ svn diff -r1000:2000 http://host/repos/trunk/foo.c ...