This article explains how to perform version control using Subversion (Linux or Windows server) and SVN (Linux client) or TortoiseSVN (Windows client).
Install package while installing Linux, or from the menu Start > System > Add/Remove Software.
Create a directory where future repositories will be stored. Note: this is not the repository, but a container to the repositories.
$ mkdir /data/repos
Create a specific user to run Subversion. Create system account for svnuser
(use repository directory as home directory):
$ /usr/sbin/groupadd -r svnuser $ /usr/sbin/useradd -g svnuser -c "Subversion User" -d /data/repos -s /bin/bash -r -l -n svnuser
Run Subversion server (svnserve). Restrict Subversion to allow exporting trees only under a specific directory (-d for daemon, -T for threaded, -r for root directory). Execute one of these commands (assuming the repository is in /data/repos
):
$ svnserve -d -T -r /data/repos $ sudo -u svnuser svnserve -d -T -r /data/repos $ su -l svnuser -c "svnserve -d -T -r /data/repos"
Add exception rule to firewall to allow traffice through port 3690 on the subversion server. In Ubuntu:
$ ufw status $ # Only to 192.168.0.31: ufw allow from 192.168.0.0/24 to 192.168.0.31 port 3690 $ ufw allow from 192.168.0.0/24 to any port 3690
Note for SELinux / Fedora Core 3+ / Red Hat Enterprise users 1) :
In addition to regular Unix permissions, under SELinux every file, directory, process, etc. has a 'security context'. When a process attempts to access a file, besides checking the Unix permissions the system also checks to see if the security context of the process is compatible with the security context of the file.
Fedora Core 3, among other systems, comes with SELinux installed by default, configured so that Apache runs in a fairly restricted security context. To run Subversion under Apache, you have to set the security context of the repository to allow Apache access (or turn off the restrictions on Apache, if you think all this is overkill). The chcon command is used to set the security context of files (similarly to how the chmod sets the traditional Unix permissions). For example, one user had to issue this command
$ chcon -R -h -t httpd_sys_content_t PATH_TO_REPOSITORY
to set the security context to be able to successfully access the repository.
Create a script to launch svnserve
at server boot time. The file should be called /etc/init.d/svnserve
:
#!/bin/bash # # Startup script for the Subversion's SVNSERVE # # chkconfig: - 85 15 # description: Subversion is an excellent VCS. # processname: svnserve # pidfile: /var/run/subversion.pid # config: /etc/subversion.conf or /etc/subversion/config ? # # Author: Dejan Lekic, dejan@nu6.org, http://dejan.lekic.org # Version: 1.0 # Modification: # 2005.01.11 by Wan-rong Jih # 2006.08.17 by Siegwart Mayr # # Source function library. . /etc/rc.d/init.d/functions # This will prevent initlog from swallowing up a pass-phrase prompt. INITLOG_ARGS="" # Path to the svnserve binary. svnserve_prog=/usr/bin/svnserve svnserve_exec=svnserve svnserve_pidf=/var/run/subversion.pid svnserve_user=svnuser svnserve_repo=/data/repos RETVAL=0 start() { echo -n $"Starting $svnserve_exec: " #echo -n $"Executing $svnserve_prog -d -T -r $svnserve_repo" echo -n $"Repository => $svnserve_repo" su -l $svnserve_user -c $"$svnserve_prog -d -T -r $svnserve_repo" RETVAL=$? #echo [ $RETVAL = 0 ] && touch /var/lock/subsys/subversion [ $RETVAL -eq 0 ] && echo_success [ $RETVAL -ne 0 ] && echo_failure echo `/sbin/pidof svnserve` > $svnserve_pidf echo return $RETVAL } stop() { echo -n $"Stopping $prog: " killproc $svnserve_exec RETVAL=$? echo [ $RETVAL = 0 ] && rm -f /var/lock/subsys/subversion $svnserve_pidf } # See how we were called. case "$1" in start) start ;; stop) stop ;; status) status $svnserve_exec ;; restart) stop start ;; reload) echo -n $"Reloading $svnserve_exec: " killproc $svnserve_exec -HUP RETVAL=$? echo ;; condrestart) if [ -f $svnserve_pidf ] ; then stop start fi ;; *) echo $"Usage: $prog {start|stop|restart|reload|condrestart|status}" exit 1 esac exit $RETVAL
Create a project repository (proj1
) in directory /data/repos
:
$ svnadmin create /data/repos/proj1
Add a repository user to have access to the project. Edit file proj1/conf/passwd
to include:
[users] jdoe = mypassword123
Edit file proj1/conf/svnserve.conf
to include:
[general] password-db = passwd realm = My Realm
Set correct file permissions for project repository:
$ chmod -R 750 proj1 $ chown -R svnuser:svnuser proj1
Create layout of project:
$ mkdir tmpdir $ cd tmpdir $ mkdir proj1 $ mkdir proj1/trunk $ mkdir proj1/branches $ mkdir proj1/tags
Import a project (/tmpdir/proj1
) into the empty repository (proj1
):
$ svn import /tmpdir/proj1 svn://server1.example.com/proj1 --message "Initial import"
Checkout a copy of the project /data/repos/proj1
to create a working copy:
$ mkdir /projects/proj1 $ cd /projects/proj1 $ svn checkout svn://server1.example.com/proj1
Update your current copy with the latest repository changes:
$ svn update
Commit your changes to the repository (and log changes):
$ svn commit --message "Added a few more things"
Create or edit the file proj1/hooks/pre-revprop-change
to have the following:
# The hook program typically does not inherit the environment of # its parent process. For example, a common problem is for the # PATH environment variable to not be set to its usual value, so # that subprograms fail to launch unless invoked via absolute path. # If you're having unexpected problems with a hook program, the # culprit may be unusual (or missing) environment variables. # # Here is an example hook script, for a Unix /bin/sh interpreter.# For more examples and pre-written hooks, see those in # the Subversion repository at # http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and # http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/ REPOS="$1" REV="$2" USER="$3" PROPNAME="$4" ACTION="$5" if [ "$ACTION" = "M" -a "$PROPNAME" = "svn:log" ]; then exit 0; fi echo "Changing revision properties other than svn:log is prohibited" >&2 exit 1
Make sure the file is owned by svnuser:svnuser
and permissions are set to user read-execute (-r-x——
).
D:\repos
D:\repos\ezfit4
D:\repos\ezfit4\
C:\proj\ezfit4\
C:\proj\ezfit4\trunk C:\proj\ezfit4\branches C:\proj\ezfit4\tags
Create a Windows service to run server (svnserve.exe). This allows the system to run the server without needing a user to be logged in.
C:\Program Files\Subversion\bin
).C:\> cd C:\Program Files\Subversion\bin\ C:\> SVNService -install -d -r D:\repos
SVNService -install
<svnserve parameters>
to install the service.SVNService -setup
<svnserve parameters>
to change command line parameters for svnserve.SVNService -remove
to remove the service.
Under repository, create/edit a file conf/svnserve.conf
with the following (For example: D:\repos\ezfit4\conf\svnserve.conf
):
[general] anon-access = none auth-access = write password-db = passwd realm = MyProject
Under repository, create/edit a file conf/passwd
with the following (For example: D:\repos\ezfit4\conf\passwd
):
[users] smayr = mypasswordhere joel = anotherpasswordhere
The default svnserve setup provides anonymous read-only access, so whilst you can use the repo-browser in TortoiseSVN to view a repository using an svn://
URL, you won't be able to perform any normal Subversion operations such as checkout, update or commit.
To enable write access to a repository, you need to edit the conf/svnserve.conf
file in your repository directory. This file controls the configuration of the svnserve daemon, and also contains useful documentation.
You can enable anonymous write access by simply setting:
[general] anon-access = write
However, you will not know who has made changes to a repository, as the svn:author
property will be empty. You will also be unable to control who makes changes to a repository. This is a somewhat risky setup!
One way to overcome this is to create a password database:
[general] anon-access = none auth-access = write password-db = password.conf
Where password.conf is a file which exists in the same location as svnserve.conf
, it can also exist on a path relative to the conf
directory and has a structure of:
[users] username = password ...
This example would deny all access for unauthenticated (anonymous) users, and give read-write access to all users in the password.conf
file.
If you have multiple repositories, then setting up an authentication realm should make administration easier. For example, if you have two repositories, creatively named TestRepo and TestRepo2, and they both live as sub-directories under c:\repos
, to setup an authentication realm between them:
c:\repos\TestRepo\conf\svnserve.conf
[general] anon-access = read auth-access = write password-db = password.conf
c:\repos\TestRepo2\conf\svnserve.conf
[general] realm = /TestRepo
TestRepo2 now shares the same password database as TestRepo, which gives read-only unauthenticated (anonymous) access and read-write access for authenticated users.
Point browser or SVN client (TortoiseSVN or RapidSVN) to repository. For example: svn://localhost/ezfit4
Open hooks directory in repository: D:\repos\ezfit4\hooks
Create file pre-revprop-change.bat
file in that folder with these contents (For example: D:\repos\ezfit4\hooks\pre-revprop-change.bat
):
rem # PRE-REVPROP-CHANGE HOOK rem # Only allow log messages to be changed. if "%4" == "svn:log" exit 0 echo Property '%4' cannot be changed >&2 exit 1
Perform previous steps for each repository that needs log editing.
Create a Branch/Tag
To create a branch (or tag), simply use one of the following:
copy
command: % svn copy SRC DST
svn://server/projname/branches/projname-1.0