SVN Tutorial

Sixteenth of the first lunar month
Because the coronavirus in 2020 has not passed yet, I studied at home to use docker to deploy the subversion server in Kali-linux.

Apache Subversion (often abbreviated SVN, after its command name svn) is a software versioning and revision control system distributed as open source under the Apache License.[2] Software developers use Subversion to maintain current and historical versions of files such as source code, web pages, and documentation. Its goal is to be a mostly compatible successor to the widely used Concurrent Versions System (CVS).

Docker

Here use the latest version of Docker-ce, as for how to install please see Install Docker-Ce and Images
When installing, you need to pay attention to the system version of Docker-Ce. Because kali-Rolling is built on the latest version of Debian, when running get-docker.sh, there will be no kali-rolling version error. At this time, we need to correct some mistakes to docker.list.

1
2
:~$ sed -i 's|kali-rolling|buster|' /etc/apt/sources.list.d/docker.list
:~$ sudo apt-get update && sudo apt-get install docker-ce

svn-server images

Here we use the svn-server image of garethflowers. Because its image is open source and the smallest.

Install

  • Install from hub.Docker.com
    1
    :~$ sudo docker pull garethflowers/svn-server
  • Build from source code
    1
    2
    :~$ git clone https://github.com/garethflowers/docker-svn-server.git
    :~$ cd docker-svn-server.git && sudo docker build -t garethflowers/svn-server .

Start a Subversion Server instance

To start a container, with data stored in /home/svn on the host, use the following:

1
:~$ sudo docker run --name my-svn-server --detach --volume /home/svn:/var/opt/svn --publish 3690:3690  garethflowers/svn-server
  • --volume:Map /var/opt/svn in the image to /home/svn on the physical machine.
  • --publish:Map Docker port 3690 to the physical machine.

Creating new SVN Repository

Use svnadmin within your container to create and manage repositories.

For example, to create a repository called test in container my-svn-server, use the following:

1
2
3
4
5
# Method 1
:~$ sudo docker exec -it my-svn-server svnadmin create test
# Method 2
:~$ sudo docker exec -it my-svn-server env TERM=xterm sh -l
262982ca78f2:/var/opt/svn$ svnadmin create test

Configure

Start way

  • Method One:Multi-library svnserve mode (specified to the parent directory of the repository), the default startup mode.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    :~$ sudo docker exec -it my-svn-server env TERM=xterm sh -l
    262982ca78f2:/var/opt/svn$ cd test
    262982ca78f2:/var/opt/svn/test$ vi conf/svnserve.conf
    [general]
    anon-access = none
    auth-access = write
    password-db = passwd
    authz-db = authz
    262982ca78f2:/var/opt/svn/test$ vi conf/passwd
    [users]
    admin = password
    test1 = test1_password
    test2 = test2_password
    262982ca78f2:/var/opt/svn/test$ vi conf/authz
    [groups]
    g_admin = admin,test1
    g_dev = test2

    [/]
    test1 = r
    * =

    [test:/]
    @g_admin = rw
    * =

    [test_2:/]
    @g_admin = rw
    * =
    The client uses svn ls svn: //192.168.0.1/test to access the test repository.
  • Method Two:Single library mode (-r serves only one library)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    :~$ sudo docker exec -it my-svn-server env TERM=xterm sh -l
    262982ca78f2:/var/opt/svn$ killall /usr/bin/svnserve
    262982ca78f2:/var/opt/svn$ /usr/bin/svnserve --daemon --foreground --root /var/opt/svn/test
    262982ca78f2:/var/opt/svn$ cd test
    262982ca78f2:/var/opt/svn/test$ vi conf/svnserve.conf
    [general]
    anon-access = none
    auth-access = write
    password-db = passwd
    authz-db = authz
    262982ca78f2:/var/opt/svn/test$ vi conf/authz
    [groups]
    g_admin = admin,test1
    g_dev = test2

    [/]
    test1 = r
    @g_admin = rw
    * =
    262982ca78f2:/var/opt/svn/test$ vi conf/passwd
    [users]
    admin = password
    test1 = test1_password
    test2 = test2_password
    The client uses svn ls svn: //192.168.0.1/ to access the test repository.

svnserve.conf

1
2
3
4
5
6
[general]
anon-access = none
auth-access = write
password-db = /var/opt/svn/passwd
authz-db = /var/opt/svn/authz
# realm =
  • anon-access: Controls the permissions of non-authenticated users to access the repository. The value range is write/read/none. That is, write is readable and writable, read is read-only, and none means no access.
    Default: read
  • auth-access: Controls the permission of authentication users to access the repository. The value range is write/read/none. That is, write is readable and writable, read is read-only, and none means no access.
    Default: write
  • password-db:Specifies the name of the user password file, which is used to add or delete svn users. Unless an absolute path is specified, the file location is relative to the conf directory.
    Default:passwd
    Example: /home/svn/passwd
  • authz-db: Specifies the name of a rights configuration file, which can be used to implement path-based access control. Unless an absolute path is specified, the file location is relative to the conf directory.
    Default: authz
  • realm: Specify the authentication domain of the repository, that is, the name of the authentication domain that is prompted during login. If the authentication domains of the two repositories are the same, it is recommended to use the same username and password data files.
    Default: UUID (Universal Unique IDentifier)

passwd

1
2
3
4
5
[users]
# <user name> = <password>
admin = 12346789
admin02 = 987654321
test = test

The username and password file is specified by the configuration item password-db in svnserve.conf and defaults to passwd in the conf directory. The file consists of only one [users] configuration section.

authz

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[groups]
# <group name> = <group users>
g_admin = admin,admin02
g_test = test

[test:/]
# [Repository:Path]
admin = rw
* =
# rw --- read and write
# r --- read
# --- null, couldn't read and write
[/]
# All Repository
@g_admin = rw

The rights configuration file is specified by the configuration item authz-db in svnserve.conf. The default is authz in the conf directory. The configuration file consists of a [groups] configuration user group and several repository path permission sections.

SVN Client

  1. Pull Repository
    1
    2
    3
    4
    5
    6
    7
    :~$ svn checkout svn://192.168.0.1/test --username=admin --password=123456789
    Checked out revision 0.
    # The remote library is empty, the revision value here is 0. After a successful checkout, a test copy directory is generated in the current directory. View Pulled Content
    :~$ ls -lah test
    drwxr-xr-x 2 root root 4.0K Feb 9 11:52 .
    drwxr-xr-x 6 root root 4.0K Feb 9 11:50 ..
    drwxr-xr-x 4 root root 4.0k Feb 9 11:53 .svn/
  2. Add new file
    1
    2
    3
    :~$ cd test && echo "Test 01" > test.md
    :~/test$ svn add ./*
    A test.md
  3. Push Repository
    1
    2
    3
    4
    5
    :~/test$ svn commit -m "add first file"
    Adding test.md
    Transmitting file data .done
    Committing transaction...
    Committed revision 1.
  4. View file changes
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    :~/test$ echo "Test 02" >> test.md
    :~/test$ svn diff
    Index: test.md
    ===================================================================
    --- test.md (revision 1)
    +++ test.md (working copy)
    @@ -1 +1,2 @@
    Test 01
    +Test 02
    :~/test$

Client Configuration

The configuration file is located at ~/.subversion.

1
2
3
4
5
:~$ ls -lah ~/.subversion
drwx------ 6 root root 4.0K Feb 20 2018 auth
-rw-r--r-- 1 root root 8.5K Feb 20 2018 config
-rw-r--r-- 1 root root 4.2K Feb 20 2018 README.txt
-rw-r--r-- 1 root root 8.2K Feb 20 2018 servers

config

There is an important parameter password-stores in this configuration file, that is, the authenticated user name and password are cached locally, so that you do not need to enter the user name and password each time you submit changes.

However, there is a disadvantage, after our user password is modified on the server side, we will report an incorrect password error when we resubmit the file locally. So we need to manually delete the cache under ~/.subversion/auth and relogin.

To do this, we can also set this value to blank to prevent subversion from caching user login credentials.

Resolve conflict

Suppose that both A and B users update the HelloWorld.html file when the version number is 100. User A submits HelloWorld.html to the server after the modification is completed. After successful submission, the version number of the HelloWorld.html file has become 101. User B also made changes to the HelloWorld.html file with version number 100. When the modification was completed and submitted to the server, the submission failed because it was not made on the current latest version 101.

At this point we need svn update to update the version of the conflicting file, and then submit the update.

1
2
3
4
5
6
7
8
9
10
11
:~/test$ svn update
Updating '.':
C HelloWorld.html
Updated to revision 6.
Conflict discovered in file 'HelloWorld.html'.
Select: (p) postpone, (df) show diff, (e) edit file, (m) merge,
(mc) my side of conflict, (tc) their side of conflict,
(s) show all options: mc
Resolved conflicted state of 'HelloWorld.html'
Summary of conflicts:
Text conflicts: 0 remaining (and 1 already resolved)

Enter mc here, mainly local files. You can also use its options to perform different operations on conflicting files.

The default is to update to the latest version, we can also specify which version to update to svn update -r6.

At this point, the working copy is synchronized with the server and it is safe to commit changes.

1
2
3
4
:~/test$ svn commit -m "change HelloWorld.html second"
Sending HelloWorld.html
Transmitting file data .
Committed revision 7.

Version rollback

When we want to abandon the modification of the file, we can use the SVN revert command.

svn revert will undo any local changes in any file or directory.

We modify the file readme to see the file status.

1
2
:~$ svn status
M readme

At this time, we found a error. To undo the modification, return to the unmodified state through the svn revert file readme.

1
2
:~$ svn revert readme
Reverted 'readme'

Check status again.

1
2
:~$ svn status
:~$

After the revert operation, the readme file is restored to its original state. The revert operation not only restores a single file, but also restores the entire directory. Use the -R command to restore the directory, as follows.

1
svn revert -R trunk

But what if we want to restore a committed version.

In order to eliminate an old version, we must undo all changes in the old version and commit a new version. This operation is called reverse merge.

First, find the current version of the repository, which is now version 22. We want to undo the previous version, such as version 21.

1
svn merge -r 22:21 readme

History information

  • svn log: Used to show the version author, date, path, etc. of svn.
    1
    2
    3
    4
    # View changes between version 6 and version 8.
    :~$ svn log -r 6:8
    # View the history information of a specified file
    :~$ svn log HelloWorld.html
  • svn diff: Used to display row-level details of a particular modification.
    1
    2
    3
    4
    # View changes in workspace and repository
    :~$ svn diff
    # View changes in workspace files and repository number 3.
    :~$ svn diff -r 3 rule.txt
  • svn cat: Get a file in a specific version to display on the current screen.
    1
    2
    # View file contents of past versions
    :~$ svn cat -r Version rule.txt
  • svn list: Displays files that exist in a directory or a version.
    1
    2
    3
    # View files in a remote directory
    :~$ svn list svn://192.168.0.1/test
    test.md

SVN Branch

The Branch option creates another route for the developer. This option is useful when someone wants to separate the development process into two different lines.

For example, there are two groups under the project demo and a trunk version under svn.

Due to the sudden changes in customer requirements, the project needs to make major changes. At this time, the project team decides that Team 1 will continue to complete half of the work (a certain module), and Team 2 will develop new requirements.

Then at this point, we can create a branch for group 2. The branch is actually a copy of the trunk version (trunk), but the branch also has version control and is independent of the trunk. Of course, in the end We can use the (merge) function to merge the branches into the trunk, and finally merge into a project.

1
2
3
4
5
6
:~$ svn copy src/ branches/my_src
:~$ svn commit -m "add my_branch"
:~$ cd branches/my_src
:~/branches/my_src$ svn add ./*
:~/branches/my_src$ svn commit -m "add ....."
:~/branches/my_src$ svn merge branches/my_src

References:
wikipedia
runoob
docker
Install Docker and Images