Home | 简体中文 | 繁体中文 | 杂文 | Github | 知乎专栏 | 51CTO学院 | CSDN程序员研修院 | OSChina 博客 | 腾讯云社区 | 阿里云栖社区 | Facebook | Linkedin | Youtube | 打赏(Donations) | About
知乎专栏多维度架构

第 127 章 Subversion

目录

127.1. Invoking the Server
127.1.1. Installing
127.1.2. standalone “daemon” process
127.1.3. classic Unix-like inetd daemon
127.1.4. hooks
127.1.5. WebDav
127.2. repository 管理
127.2.1. create repository
127.2.2. user admin
127.2.3. authz
127.2.4. dump
127.3. 使用Subversion
127.3.1. Initialized empty subversion repository for project
127.3.2. ignore
127.3.3. 关键字替换
127.3.4. lock 加锁/ unlock 解锁
127.3.5. import
127.3.6. export 指定版本
127.3.7. 修订版本关键字
127.3.8. 恢复旧版本
127.4. branch
127.4.1. create
127.4.2. remove
127.4.3. switch
127.4.4. merge
127.4.5. relocate
127.5. FAQ
127.5.1. 递归添加文件
127.5.2. 清除项目里的所有.svn目录
127.5.3. color diff
127.5.4. cvs2svn
127.5.5. Macromedia Dreamweaver MX 2004 + WebDAV +Subversion
127.5.6. 指定用户名与密码

127.1. Invoking the Server

配置开发环境版本控制Subversion

Squid + Subversion 请参考Squid一节

127.1.1. Installing

127.1.1.1. Ubuntu

过程 127.1. subversion

  1. installation

    $ sudo apt-get install subversion
    $ sudo apt-get install subversion
    					
  2. create svn group and svnroot user

    $ sudo groupadd svn
    $ sudo adduser svnroot --ingroup svn
    					
  3. create repository

    $ svnadmin create /home/svnroot/test
    					
  4. testing

    svnroot@netkiller:~$ svnserve -d --foreground -r /home/svnroot/
    					

    check out

    neo@netkiller:/tmp$ svn list svn://localhost/test

    you may see some file and directory

    neo@netkiller:/tmp$ ls test/.svn/
    entries  format  prop-base  props  text-base  tmp
    					
  5. configure

    $ vim repositories/conf/svnserve.conf

    [general]
    anon-access = read
    auth-access = write
    password-db = passwd
    # authz-db = authz
    # realm = My First Repository
    					

    $ vim repositories/conf/passwd

    [users]
    # harry = harryssecret
    # sally = sallyssecret
    neo = chen
    					

    如果不允许匿名用户checkout代码,配置文件这样写anon-access = none

    [general]
    anon-access = none
    auth-access = write
    					
  6. firewall

    $ sudo ufw allow svn
    					

127.1.1.2. CentOS 5

		
[root@development ~]# yum -y install subversion
		
		
classic Unix-like xinetd daemon
			
[root@development ~]# vim /etc/xinetd.d/subversion
service subversion
{
    disable = no
    port = 3690
    socket_type = stream
    protocol = tcp
    wait = no
    user = svnroot
    server = /usr/bin/svnserve
    server_args = -i -r /home/svnroot
}
			
			

firewall

			
iptables -A INPUT -p tcp -m tcp --sport 3690 -j ACCEPT
iptables -A OUTPUT -p tcp -m tcp --dport 3690 -j ACCEPT
			
			
WebDav

install webdav module

			
[root@development ~]# yum install mod_dav_svn
			
			

create directory

			
mkdir /var/www/repository
svnadmin create /var/www/repository
			
			

subversion.conf

			
[root@development ~]# vim /etc/httpd/conf.d/subversion.conf
LoadModule dav_module modules/mod_dav.so
LoadModule dav_svn_module modules/mod_dav_svn.so
LoadModule authz_svn_module modules/mod_authz_svn.so
			
			

vhost.conf

			
<Location />
DAV svn
SVNPath /var/www/repository
AuthType Basic
AuthName "Subversion Repository"
AuthUserFile /etc/subversion/svn-auth-file
Require valid-user
</Location>
			
			

auth file

			
[root@development ~]# htpasswd -c /etc/subversion/svn-auth-file my_user_name
			
			
项目目录结构

–trunk #存放主线

–branches #存放分支,可修改

–tags #存放标记,不可修改

127.1.1.3. CentOS 6

CentOS 6 默认没有安装xinetd

# yum install xinetd
# yum install subversion

# mkdir -p /opt/svnroot
			

xinetd 配置

# vim /etc/xinetd.d/svn
service svn
{
    disable = no
    port = 3690
    socket_type = stream
    protocol = tcp
    wait = no
    user = svnroot
    server = /usr/bin/svnserve
    server_args = -i -r /opt/svnroot
}

# /etc/init.d/xinetd restart
Stopping xinetd:                                           [FAILED]
Starting xinetd:                                           [  OK  ]

# tail /var/log/messages | grep xinetd
May  5 18:57:20 SZVM42-C1-02 yum: Installed: 2:xinetd-2.3.14-16.el5.i386
May  5 18:59:22 SZVM42-C1-02 xinetd[4558]: Unknown user: svnroot [file=/etc/xinetd.d/svn] [line=8]
May  5 18:59:22 SZVM42-C1-02 xinetd[4558]: Error parsing attribute user - DISABLING SERVICE

[file=/etc/xinetd.d/svn] [line=8]
May  5 18:59:22 SZVM42-C1-02 xinetd[4558]: xinetd Version 2.3.14 started with libwrap loadavg labeled-networking

options compiled in.
May  5 18:59:22 SZVM42-C1-02 xinetd[4558]: Started working: 0 available services
			

service 名字必须与 /etc/services中定义的名字相同,否则将不能启动,同时在/var/log/message中会提示如下

May  4 14:33:08 www xinetd[5656]: service/protocol combination not in /etc/services: subversion/tcp
May  4 14:33:08 www xinetd[5656]: xinetd Version 2.3.14 started with libwrap loadavg labeled-networking options compiled in.
May  4 14:33:08 www xinetd[5656]: Started working: 0 available services
May  4 14:33:33 www pulseaudio[21913]: sink-input.c: Failed to create sink input: too many inputs per sink.
May  4 14:33:33 www pulseaudio[21913]: sink-input.c: Failed to create sink input: too many inputs per sink.
May  4 14:33:33 www pulseaudio[21913]: sink-input.c: Failed to create sink input: too many inputs per sink.
May  4 14:33:33 www pulseaudio[21913]: sink-input.c: Failed to create sink input: too many inputs per sink.
May  4 14:33:33 www pulseaudio[21913]: sink-input.c: Failed to create sink input: too many inputs per sink.
May  4 14:33:33 www pulseaudio[21913]: sink-input.c: Failed to create sink input: too many inputs per sink.
May  4 14:33:33 www pulseaudio[21913]: sink-input.c: Failed to create sink input: too many inputs per sink.
May  4 14:33:33 www pulseaudio[21913]: sink-input.c: Failed to create sink input: too many inputs per sink.
May  4 14:33:41 www xinetd[5656]: Exiting...
May  4 14:33:41 www xinetd[5676]: xinetd Version 2.3.14 started with libwrap loadavg labeled-networking options compiled in.
May  4 14:33:41 www xinetd[5676]: Started working: 1 available service
			

127.1.2. standalone “daemon” process

svn daemon

$ svnserve --daemon --root /home/svnroot
		

127.1.2.1. starting subversion for debian/ubuntu

/etc/init.d/subversion for debian/ubuntu

			
debian:/etc/init.d# cat subversion
#!/bin/sh
### BEGIN INIT INFO
# Provides:          subversion
# Required-Start:    $remote_fs $network
# Required-Stop:     $remote_fs $network
# Should-Start:      fam
# Should-Stop:       fam
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start the subversion subversion server.
### END INIT INFO

#########################
# Author: Neo <openunix@163.com>
#########################

PATH=/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/bin/svnserve
NAME=subversion
DESC="subversion server"
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME
SVNROOT=/srv/svnroot
DAEMON_OPTS="-d -T -r $SVNROOT --pid-file $PIDFILE"

test -x $DAEMON || exit 0

set -e

. /lib/lsb/init-functions

case "$1" in
    start)
        log_daemon_msg "Starting $DESC" $NAME
        echo
        $DAEMON $DAEMON_OPTS
        echo `pgrep -o $NAME` > $PIDFILE > /dev/null 2> /dev/null
        ;;
    stop)
        log_daemon_msg "Stopping $DESC" $NAME
        echo
        killall `basename $DAEMON` > /dev/null 2> /dev/null
        rm -rf $PIDFILE
        ;;
    restart)
        $0 stop
        $0 start
        ;;
    status)
        ps ax | grep $NAME
        ;;
    *)
        echo "Usage: $SCRIPTNAME {start|stop|restart|status}" >&2
        exit 1
        ;;
esac

exit 0
			
			

127.1.2.2. starting subversion daemon script for CentOS/Radhat

			
#!/bin/bash
#
# /etc/rc.d/init.d/subversion
#
# Starts the Subversion Daemon
#
# chkconfig: 345 90 10
#
# description: Subversion Daemon

# processname: svnserve

source /etc/rc.d/init.d/functions

[ -x /usr/bin/svnserve ] || exit 1

### Default variables
SYSCONFIG="/etc/sysconfig/subversion"

### Read configuration
[ -r "$SYSCONFIG" ] && source "$SYSCONFIG"

RETVAL=0
USER="svnroot"
prog="svnserve"
desc="Subversion Daemon"

start() {
   echo -n $"Starting $desc ($prog): "
   daemon --user $USER $prog -d $OPTIONS
   RETVAL=$?
   [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$prog
   echo
}

stop() {
   echo -n $"Shutting down $desc ($prog): "
   killproc $prog
   RETVAL=$?
   [ $RETVAL -eq 0 ] && success || failure
   echo
   [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$prog
   return $RETVAL
}

case "$1" in
  start)
   start
   ;;
  stop)
   stop
   ;;
  restart)
   stop
   start
   RETVAL=$?
   ;;
  condrestart)
        [ -e /var/lock/subsys/$prog ] && restart
   RETVAL=$?
   ;;
  *)
   echo $"Usage: $0 {start|stop|restart|condrestart}"
   RETVAL=1
esac

exit $RETVAL
			
			

/etc/sysconfig/subversion

# Configuration file for the Subversion service

#
# To pass additional options (for instace, -r root of directory to server) to
# the svnserve binary at startup, set OPTIONS here.
#
#OPTIONS=
OPTIONS="--threads --root /srv/svnroot"
				

127.1.3. classic Unix-like inetd daemon

/etc/inetd.conf

svn stream tcp nowait svn /usr/bin/svnserve svnserve -i -r /home/svnroot/repositories
			

xinetd.d

/etc/xinetd.d/subversion

$ sudo apt-get install xinetd
$ sudo vim /etc/xinetd.d/subversion

service subversion
{
    disable = no
    port = 3690
    socket_type = stream
    protocol = tcp
    wait = no
    user = svnroot
    server = /usr/bin/svnserve
    server_args = -i -r /home/svnroot
}
			

restart xinetd

$ sudo /etc/init.d/xinetd restart
			

127.1.4. hooks

$ sudo apt-get install subversion-tools
			

127.1.4.1. post-commit

install SVN::Notify

perl -MCPAN -e 'install SVN::Notify'
				
				
$ sudo cp post-commit.tmpl post-commit
$ sudo chown svnroot:svn post-commit
$ sudo vim post-commit

REPOS="$1"
REV="$2"

#/usr/share/subversion/hook-scripts/commit-email.pl "$REPOS" "$REV" openunix@163.com
/usr/share/subversion/hook-scripts/commit-email.pl "$1" "$2" --from neo@netkiller.8800.org -h localhost  -s "[SVN]" --diff y openunix@163.com openx@163.com
				
				

另一种方法

				
#!/bin/sh

REPOS="$1"
REV="$2"

/usr/local/bin/svnnotify                    \
    --repos-path    "$REPOS"                \
    --revision      "$REV"                  \
    --subject-cx                            \
    --with-diff                             \
    --handler       HTML::ColorDiff         \
    --to            <your e-mail address>   \
    --from          <from e-mail address>
    			
				
/usr/bin/svnnotify --repos-path "$REPOS" --revision "$REV" \
--from neo@netkiller.8800.org --to openunix@163.com --smtp localhost \
--handler "HTML::ColorDiff"  --with-diff --charset zh_CN:GB2312  -g zh_CN --svnlook /usr/bin/svnlook --subject-prefix '[SVN]'
				

如果你没有安装邮件服务器,你可以使用服务商的SMTP如163.com

/usr/bin/svnnotify --repos-path "$REPOS" --revision "$REV" \
--from openx@163.com --to openunix@163.com --smtp smtp.163.com  --smtp-user openunix --smtp-pass ****** \
--handler "HTML::ColorDiff"  --with-diff --charset UTF-8 --language zh_CN --svnlook /usr/bin/svnlook --subject-prefix '[SVN]'
				

Charset

REPOS="$1"
REV="$2"

svnnotify --repos-path "$REPOS" --revision "$REV" \
        --subject-cx \
        --from neo.chen@example.com \
        --to group@example.com,manager@example.com \
        --with-diff \
        --svnlook /usr/bin/svnlook \
        --subject-prefix '[SVN]' \
        --charset UTF-8  --language zh_CN
				

127.1.5. WebDav

Apache SVN

$ sudo apt-get install libapache2-svn
netkiller@neo:/etc/apache2$ sudo apt-get install libapache2-svn
			

vhost

			
<VirtualHost *>
        ServerName svn.netkiller.8800.org
        DocumentRoot /var/svn

      <Location />
                DAV svn
                SVNPath /var/svn
                AuthType Basic
                AuthName "Subversion Repository"
                AuthUserFile /etc/apache2/svn.passwd
                <LimitExcept GET PROPFIND OPTIONS REPORT>
                        Require valid-user
                </LimitExcept>
        </Location>
</VirtualHost>
			
			

建立密码文件

建立第一个用户需要加-c参数

netkiller@neo:/etc/apache2$ sudo htpasswd2 -c /etc/apache2/svn.passwd svn
New password:
Re-type new password:
Adding password for user svn
			

输入两次密码

建立其他用户

sudo htpasswd2 /etc/apache2/svn.passwd otheruser
			

127.1.5.1. davfs2 - mount a WebDAV resource as a regular file system

install

$ sudo apt-get install davfs2
				

mount a webdav to directory

$ sudo mount.davfs https://opensvn.csie.org/netkiller /mnt/davfs/
Please enter the username to authenticate with server
https://opensvn.csie.org/netkiller or hit enter for none.
Username: svn
Please enter the password to authenticate user svn with server
https://opensvn.csie.org/netkiller or hit enter for none.
Password:
mount.davfs: the server certificate is not trusted
  issuer:      CSIE.org, CSIE.org, Taipei, Taiwan, TW
  subject:     CSIE.org, CSIE.org, Taipei, TW
  identity:    *.csie.org
  fingerprint: e6:05:eb:fb:69:5d:25:4e:11:3c:83:e8:7c:44:ee:bf:a9:85:a3:64
You only should accept this certificate, if you can
verify the fingerprint! The server might be faked
or there might be a man-in-the-middle-attack.
Accept certificate for this session? [y,N] y
				

test

$ ls davfs/
branches  lost+found  tags  trunk