Sonntag, 14. August 2011

Yet Another Subversion Introduction

Concept

Subversion organizes your data at two distinct places. The server holds the repository. This contains the full set of files. For every file its current (i.e. most up to date) version is kept. Additionally the full history (i.e. all previous versions) of every file is kept. Usually you will be interested in the current version of all files, but at certain circumstances (e.g. doing a release, correcting bugs in such releases, comparing your changes to previous versions, ...) you will need the old versions of the files.

Everybody who wants to work with these files has to check out his own working copy from the repository. These are normal files at your hard disk where you can work on with every program (e.g. editor, ...) you want. When you have done your changes to the files, you commit these changes back to the repository. Thats how a new version of several files is generated.

It is important to know, that SVN numbers these versions with a progressive integer starting from 0. This number is called the revision. All current files within the repository have the same revision number. This is different to SVN's predecessor CVS which had a separate revision number for every file.

But what happens when several people have checked out their working copies and do independent changes. They commit their changes at different times. But SVN will not let the later one commit his changes. First he has to update his working copy and it is SVN's job to merge all these changes of the other people into the working copy. Usually this works fine, even if two persons make changes to the same file, as long as these changes occur at different places in this file.

Now think of your working copy. When somebody commits his changes to the repository, your working copy will not be notified of this repository change and thus gets outdated. This is what the SVN update command is for. It retrieves the must up-to-date revision from the repository and merges these change into your working copy. Note that update is the smartest subcommand of SVN. It will not destroy your own changes.

Background info: Your working copy stores every file twice on your harddisk. Once for you and a second time in a hidden directory ( .svn/text-base/filename.ext.svn-base). The disadvantage is that a working copy uses twice the disk space as you expected. The advantage is that no network connection is necessary to compare your changes to the originally checked-out revision.

CLI Frontend

There exist several front ends for SVN. Here only the command line interface is described. SVN can give you help in any situaion. Simply type
svn help
You can even get info about every subcommand like
svn help checkout

Several subcommands exist:

CommandDescription
svn checkout [svnpath] get a working copy from the repository or part of it (1) (5) (6)
svn update update your working copy with the newest revision from the repository (5) (7)
svn status compare your working copy with the repository (exactly: the copy in the hidden directory) and show which files you have modified, added, removed, ... (7)
svn diff [file] compare a file to its hidden twin
svn commit upload your changes to the server and integrate them into the repository, a new revision is created (5) (7)
svn add [file] add a files or directories (recursively) to the version control (2)
svn mkdir [dir] create a new directory (2)
svn cp [file1] [file2] copy a file including its history (2) (3)
svn mv [file1] [file2] move a file maintaining its history (2) (4)
svn rm [file] remove a file from the current revision (2)

Some notes:

  1. You can also checkout only a part of the repository by specifying a subdirectory.
  2. Never directly create, rename or remove files or directories. Always use the SVN commands for that. Otherwise you will have troubles committing these changes. The only exception is creating new files. Just create it with the program you like and then add it to the version control.
  3. SVN can do so called cheap copies. that means that a copy of a file only uses very little space in the repository. Such copies even retain the full history of that files and directories. It is stored as just a pointer to the single instance of the original file. On the other hand, as soon as you modify the copy and commit these changes, a new trail (in terms of history) for this files is created. Therefore the original files will remain at their current states. The copies will have the full history (from when it was a single file) up until the most current file.
  4. A move (rename) is nothing else than a (cheap!) copy (maintaining the full history) followed by removing the original file.
  5. Only the subcommands "checkout", "update" and "commit" connect to the repository (i.e. server). All other commands only modify the working copy or refer to the locally stored copies of every file.
  6. Except for the "checkout" subcommand you never need the repository path (e.g. https://svn.server.tld/path/to/repository). This is stored in the hidden metadata files.
  7. You can also do an "update", "status", "commit", ... for only a subtree of your repository/working copy. Simply change your current working directory (cd) to a sub-path and invoke the desired command.
  8. When committing you are asked to enter a comment about what you have changed. Always describe your changes!!!. On Windows (TortoiseSVN) you have a dialog box with a large edit box for this comment. In Unix your default editor (defined by the environment variable EDITOR or vi as default) is launched and you can type and edit your comment. Note: vi is quit by hitting [Esc] and then typing ':wq' [Enter].

Line Endings

In plain text files (e.g. program source) the line ends are marked with special control characters. Unfortunately they are not the same across different operating systems. Unix uses the plain LF character. Windows uses CR-LF and the Mac uses CR. If your project is developed with different platforms you have to take care about that, the so called end of line (EOL) style.

Imagine a C++ source file is created on a Linux box and thus uses LF as EOL. When this file is checked out on Windows and the editor converts the EOLs to CR-LF, every single line looks changed (due to the additional CR character). This is bad practice and will disturb the usage of SVN.

To circumvent this problem, SVN can help you by doing checkout, commit and update using the native EOL-style. So in the above example the C++ file will have CR-LF when checked out on Windows, although it was saved with LF on a Linux box. When changes done on the Windows box are updated to the Linux box, their line endings will be converted to LF.

To get this assistance from SVN you have to set the property svn:eol-style to the value native for all your source files.

Linux

You can do this on Unix systems using the following command:
svn propset svn:eol-style native *.cc *.h

Windows (on existing files)

  1. right-click on the file(s)
  2. select TortoiseSVN
  3. select Properties
  4. select Add
  5. select property svn:eol-style
  6. write in the Property value native
  7. ok

Windows (on all future files)

You can do this on Windows with TortoiseSVN doing:
  1. right-click on any file
  2. select TortoiseSVN
  3. select Settings
  4. select the general tab
  5. click on edit button
  6. add after the following
    ### Section for configuring automatic properties.
    [auto-props]
    this:
    *.c = svn:eol-style=native
    *.cc = svn:eol-style=native
    *.cpp = svn:eol-style=native
    *.h = svn:eol-style=native
    *.txt = svn:eol-style=native
    *.png = svn:mime-type=image/png
    *.pdf = svn:mime-type=application/pdf
    *.jpg = svn:mime-type=image/jpeg
    Makefile = svn:eol-style=native

Keine Kommentare: