Difference between revisions of "Subversion Tutorial"

(Importing into a repository)
m (Replaced the template "nota" with "note".)
 
(3 intermediate revisions by one other user not shown)
Line 32: Line 32:
 
In a repository you will find a few folders and files
 
In a repository you will find a few folders and files
  
'''conf'''
+
<div style="padding-left: 30px">
    A directory containing repository configuration files.
+
;conf : A directory containing repository configuration files.
'''dav'''
+
;dav : A directory provided to Apache and mod_dav_svn for their private housekeeping data.
    A directory provided to Apache and mod_dav_svn for their private housekeeping data.
+
;db : Where all of your versioned data resides. This directory is either a Berkeley DB environment (full of DB tables and other things), or is an FSFS environment containing revision files.
'''db'''
+
;format : A file whose contents are a single integer value that dictates the version number of the repository layout.
    Where all of your versioned data resides. This directory is either a Berkeley DB environment (full of DB tables and other things), or is an FSFS environment containing revision files.
+
;hooks : A directory full of hook script templates (and hook scripts themselves, once you've installed some).
  '''format'''
+
;locks : A directory for Subversion's repository locking data, used for tracking accessors to the repository.
    A file whose contents are a single integer value that dictates the version number of the repository layout.
+
;README.txt : A file which merely informs its readers that they are looking at a Subversion repository.
'''hooks'''
+
</div>
    A directory full of hook script templates (and hook scripts themselves, once you've installed some).
+
'''locks'''
+
    A directory for Subversion's repository locking data, used for tracking accessors to the repository.
+
'''README.txt'''
+
    A file which merely informs its readers that they are looking at a Subversion repository.
+
  
 
You don't need to access those files, unless you are the repository's administrator. In this case you will edit the conf/snvserve.conf.
 
You don't need to access those files, unless you are the repository's administrator. In this case you will edit the conf/snvserve.conf.
Line 107: Line 102:
 
* svn checkout URL  or  svn co URL
 
* svn checkout URL  or  svn co URL
 
  For instance
 
  For instance
  svn co svn://username@svn_svr_address/test/
+
  svn co svn://username@svn_svr_address/svn/test/
 
  svn co http://username@svn_svr_address/svn/test/
 
  svn co http://username@svn_svr_address/svn/test/
  
Line 170: Line 165:
 
; C foo : File foo received Conflicting changes from the server. The changes from the server directly overlap your own changes to the file. No need to panic, though. This overlap needs to be resolved by a human (you); we discuss this situation later in this chapter.
 
; C foo : File foo received Conflicting changes from the server. The changes from the server directly overlap your own changes to the file. No need to panic, though. This overlap needs to be resolved by a human (you); we discuss this situation later in this chapter.
 
</div>
 
</div>
{{nota|CVS user: do not use '''svn -n update''' to check the status of your working copy, use svn status for that. <br/>This is much more powerful}}
+
{{note|CVS user: do not use '''svn -n update''' to check the status of your working copy, use svn status for that. <br/>This is much more powerful}}
  
 
=== svn resolved ===
 
=== svn resolved ===
Line 379: Line 374:
 
I would advice the second method, because if case of large folder to "branch", this will avoid copying all the files and folder in your working directory (indeed, often when you create a branch, it is for later or other).
 
I would advice the second method, because if case of large folder to "branch", this will avoid copying all the files and folder in your working directory (indeed, often when you create a branch, it is for later or other).
  
{{nota|Cheap Copies : Subversion's repository has a special design. When you copy a directory, you don't need to worry about the repository growing huge—Subversion doesn't actually duplicate any data. Instead, it creates a new directory entry that points to an existing tree. }}
+
{{note|Cheap Copies : Subversion's repository has a special design. When you copy a directory, you don't need to worry about the repository growing huge—Subversion doesn't actually duplicate any data. Instead, it creates a new directory entry that points to an existing tree. }}
  
 
=== Working with Your Branch ===
 
=== Working with Your Branch ===
Line 420: Line 415:
 
   Last Changed Date: 2005-09-30 09:27:38 -0700 (Fri, 30 Sep 2005)
 
   Last Changed Date: 2005-09-30 09:27:38 -0700 (Fri, 30 Sep 2005)
  
'''Nota:''' The Key Concepts Behind Branches
+
'''Note:''' The Key Concepts Behind Branches
  
 
# Unlike many other version control systems, Subversion's branches exist as normal filesystem directories in the repository, not in an extra dimension. These directories just happen to carry some extra historical information.
 
# Unlike many other version control systems, Subversion's branches exist as normal filesystem directories in the repository, not in an extra dimension. These directories just happen to carry some extra historical information.
Line 452: Line 447:
 
  (change this value to your own path)
 
  (change this value to your own path)
 
   
 
   
  cd $MYSVNDIR/repo
+
  cd $MYSVN_DIR/repo
 
  svnadmin create example/
 
  svnadmin create example/
 
  export MYSVN_URL=file://$MYSVN_DIR/repo/example
 
  export MYSVN_URL=file://$MYSVN_DIR/repo/example
Line 654: Line 649:
 
  svn revert src/dating/date.txt
 
  svn revert src/dating/date.txt
  
{{Nota|it is recommended that you use the --dry-run to simulate the merging, this way you will see which files will be changed, added, conflicted...}}
+
{{Note|it is recommended that you use the --dry-run to simulate the merging, this way you will see which files will be changed, added, conflicted...}}
 
   
 
   
 
  if you want to merge all differences from "project/trunk/src" into "v1/src"
 
  if you want to merge all differences from "project/trunk/src" into "v1/src"

Latest revision as of 21:04, 20 May 2019


Subversion

Abstract

Subversion (SVN hereafter) is a version managament system designed as a replacement for, and general improvement on, CVS. Subversion is designed to be a distributed, concurrent, expandable version control system.

To have a complete documentation on Subversion, please go and read this: http://svnbook.red-bean.com/en/1.1/index.html Those wiki pages are only a quick tutorial for our use of SVN.

And don't forget to use the 'svnadmin help' , 'svn help' commands to get information on usage and so on for a svn command.

Features

When discussing the features that Subversion brings to the version control table, it is often helpful to speak of them in terms of how they improve upon CVS's design. If you're not familiar with CVS, you may not understand all of these features. And if you're not familiar with version control at all, your eyes may glaze over unless you first read Chapter 2, Basic Concepts, in which we provide a gentle introduction to version control in general.

Subversion provides:

Directory versioning 
CVS only tracks the history of individual files, but Subversion implements a “virtual” versioned filesystem that tracks changes to whole directory trees over time. Files and directories are versioned.
True version history 
Since CVS is limited to file versioning, operations such as copies and renames—which might happen to files, but which are really changes to the contents of some containing directory—aren't supported in CVS. Additionally, in CVS you cannot replace a versioned file with some new thing of the same name without the new item inheriting the history of the old—perhaps completely unrelated—file. With Subversion, you can add, delete, copy, and rename both files and directories. And every newly added file begins with a fresh, clean history all its own.
Atomic commits 
A collection of modifications either goes into the repository completely, or not at all. This allows developers to construct and commit changes as logical chunks, and prevents problems that can occur when only a portion of a set of changes is successfully sent to the repository.
Versioned metadata 
Each file and directory has a set of properties—keys and their values—associated with it. You can create and store any arbitrary key/value pairs you wish. Properties are versioned over time, just like file contents.
Choice of network layers 
Subversion has an abstracted notion of repository access, making it easy for people to implement new network mechanisms. Subversion can plug into the Apache HTTP Server as an extension module. This gives Subversion a big advantage in stability and interoperability, and instant access to existing features provided by that server—authentication, authorization, wire compression, and so on. A more lightweight, standalone Subversion server process is also available. This server speaks a custom protocol which can be easily tunneled over SSH.
Consistent data handling 
Subversion expresses file differences using a binary differencing algorithm, which works identically on both text (human-readable) and binary (human-unreadable) files. Both types of files are stored equally compressed in the repository, and differences are transmitted in both directions across the network.
Efficient branching and tagging 
The cost of branching and tagging need not be proportional to the project size. Subversion creates branches and tags by simply copying the project, using a mechanism similar to a hard-link. Thus these operations take only a very small, constant amount of time.
Hackability 
Subversion has no historical baggage; it is implemented as a collection of shared C libraries with well-defined APIs. This makes Subversion extremely maintainable and usable by other applications and languages.

Svn repository

Repository Structure

Svn repository as itself on disk

In a repository you will find a few folders and files

conf 
A directory containing repository configuration files.
dav 
A directory provided to Apache and mod_dav_svn for their private housekeeping data.
db 
Where all of your versioned data resides. This directory is either a Berkeley DB environment (full of DB tables and other things), or is an FSFS environment containing revision files.
format 
A file whose contents are a single integer value that dictates the version number of the repository layout.
hooks 
A directory full of hook script templates (and hook scripts themselves, once you've installed some).
locks 
A directory for Subversion's repository locking data, used for tracking accessors to the repository.
README.txt 
A file which merely informs its readers that they are looking at a Subversion repository.

You don't need to access those files, unless you are the repository's administrator. In this case you will edit the conf/snvserve.conf. Otherwise, all the data contained in the repository (files, folders...) are not visible as it is for CVS. To administrate the repository, you will have to use the svnadmin, svnlookup and svn tools. It is possible to add hooks scripts to manage some pre or post commit, or many other hooks.

Administration

create a repository

  • svnadmin create path_to_repository
for instance:
   > cd /home/svn/
   > mkdir my_repo
   > svnadmin create my_repo

It will create the repository inside 'my_repo' by creating a few folders and files. There are 2 kinds of repository for subversion, one base on berkeley database (bdb), and one base of subversion's filesystem database (fsfs). By default, 'svnadmin create' will create a 'fsfs' repository, and we will use this default for our repository. (Using Berkeley db seems to lead to database corruption in some cases).

At this stage, the new repository (just created) contains no file, and the revision is 0. More information with: svnadmin help create

Importing into a repository

  • svn import [PATH] URL
svn import e:\my_src\test file:///home/svn/my_repo/test 
if PATH is ommitted, it will use the current directory  '.'

How to access a svn repository ?

The Subversion architecture can help you figuring out how things are done: Svn architecture

A SVN repository can be published by many ways:

file:/// direct repository access (on local disk) 
    : direct access is pretty useful especially when you create, import your repository

svn:// using the svn server 
    : access via custom protocol to an svnserve server (Check xinet.d on linux).

svn+ssh:// using the svn+ssh server 
    : same as svn:// but through an SSH tunnel

http:// access via WebDAV protocol 
    : the apache server has to be configured to be Subversion-aware 
    :(Pretty useful to give access to your repository to the outside world.)

https:// 
    :	same as http://, but with SSL encryption.

Thus, if all those media are provided (configuration done), you will address the repository as following:

local: 
   file:///home/svn/my_repo
   
Via the svnserve (thanks to xinet.d for linux for instance using /home/svn/ as root directory) :
   svn://login@machine/my_repo
   
Same with ssh :  
   svn+ssh://machine/my_repo
   
And using webdav (with /svn/ aliases on the root folder for subversion repository) :
   http://machine/svn/my_repo

Checkout your working copy

  • svn checkout URL or svn co URL
For instance
svn co svn://username@svn_svr_address/svn/test/
svn co http://username@svn_svr_address/svn/test/
If you want to checkout only a sub folder 'trunk/src' of your repository, you can do 
   svn co svn://username@svn_svr_address/test/trunk/src
and if you want to precise the output path
   svn co svn://username@svn_svr_address/test/trunk/src my_src
If you want to checkout a revision 123:
svn co svn://username@svn_svr_address/test/ -r123

More information with: svn help checkout

Repository and revision

Global Revision Numbers

Unlike those of many other version control systems, Subversion's revision numbers apply to entire trees, not individual files. Each revision number selects an entire tree, a particular state of the repository after some committed change. Another way to think about it is that revision N represents the state of the repository filesystem after the Nth commit. When a Subversion user talks about revision 5 of foo.c, they really mean foo.c as it appears in revision 5. Notice that in general, revisions N and M of a file do not necessarily differ!

For CVS users who are used to per-file revisions numbers, you can have a look at Appendix A, Subversion for CVS Users.

Working with your working copy

  • update and commit are very similar to CVS's update and commit
  • Most svn commands don't use repository URIs, acting directly on a local working copy. The most general form of an svn command is:
svn <command> [<options>] [<targets>]
where targets is the list of files or directories to operate on, 
and options is an optional list of flags, in the familiar fashion of most Unix command-line interfaces. 
For most svn commands, targets defaults to the current directory,
and the command operates recursively on each directory it processes
  • you have (among others) the following options which can be useful
  -q [--quiet]             : print as little as possible
  -N [--non-recursive]     : operate on single directory only

Working copy

In your working copy, you will have many .svn folder containing among other the base version of your files. This .svn area is similar to CVS folder with CVS, except it contains a lot of information. This allows you to do the status, diff, revert command without requiring the network. You should never edit the content of this .svn area. If you want to cancel an operation (like adding, deleting, or even changing a file), you should use the svn revert command.

Basic Work Cycle

Subversion has numerous features, options, bells and whistles, but on a day-to-day basis, odds are that you will only use a few of them. In this section we'll run through the most common things that you might find yourself doing with Subversion in the course of a day's work.

The typical work cycle looks like this:

  • Update your working copy : svn update
  • Make changes : svn add, svn delete, svn copy, svn move
  • Examine your changes : svn status, svn diff, svn revert
  • Merge others' changes into your working copy : svn update, svn resolved
  • Commit your changes : svn commit

svn update

  • svn update or svn up
U foo
File foo was Updated (received changes from the server).
A foo 
File or directory foo was Added to your working copy.
D foo 
File or directory foo was Deleted from your working copy.
R foo 
File or directory foo was Replaced in your working copy; that is, foo was deleted, and a new item with the same name was added. While they may have the same name, the repository considers them to be distinct objects with distinct histories.
G foo 
File foo received new changes from the repository, but your local copy of the file had your modifications. Either the changes did not intersect, or the changes were exactly the same as your local modifications, so Subversion has successfully merGed the repository's changes into the file without a problem.
C foo 
File foo received Conflicting changes from the server. The changes from the server directly overlap your own changes to the file. No need to panic, though. This overlap needs to be resolved by a human (you); we discuss this situation later in this chapter.

Information.png Note: CVS user: do not use svn -n update to check the status of your working copy, use svn status for that.
This is much more powerful

svn resolved

When you have a conflict on a file:

  • either you revert your local change (using svn revert).
  • or you can edit the file and resolve the conflict. When it is done, you have to do svn resolved on this file, otherwise you won't be able to commit your change later.

svn commit

  • svn commit or svn ci
  • you can pass the message using the -m "message" arguments (or the --message "...")
 svn ci the_file_a the_file_b -m "added the_file_a and the_file_b"

svn status

  • Unlike CVS, svn status is useful (do not use svn update like you were doing with cvs)
Here are some typical cases
> svn status
  L    abc.c               # svn has a lock in its .svn directory for abc.c
M      bar.c               # the content in bar.c has local modifications
 M     baz.c               # baz.c has property but no content modifications
X      3rd_party           # this dir is part of an externals definition
?      foo.o               # svn doesn't manage foo.o
!      some_dir            # svn manages this, but it's either missing or incomplete
~      qux                 # versioned as file/dir/link, but type has changed
I      .screenrc           # svn doesn't manage this, and is configured to ignore it
A  +   moved_dir           # added with history of where it came from
M  +   moved_dir/README    # added with history and has local modifications
D      stuff/fish.c        # this file is scheduled for deletion
A      stuff/loot/bloo.h   # this file is scheduled for addition
C      stuff/loot/lump.c   # this file has conflicts from an update
R      xyz.c               # this file is scheduled for replacement
    S  stuff/squawk        # this file or dir has been switched to a branch
  • svn status prints five columns of characters, followed by several whitespace characters, followed by a file or directory name. Columns :
  1. status of a file or directory and/or its contents.
  2. status of a file or directory's properties
  3. show whitespace or an L which means that Subversion has locked the item in the .svn working area
  4. show whitespace or a + which means that the file or directory is scheduled to be added or modified with additional attached history
  5. show whitespace or an S. This signifies that the file or directory has been switched from the path of the rest of the working copy (using svn switch) to a branch
  • The codes for the 1st column are listed here :
  • A : The file, directory, or symbolic link item has been scheduled for addition into the repository.
  • C : The file item is in a state of conflict. That is, changes received from the server during an update overlap with local changes that you have in your working copy. You must resolve this conflict before committing your changes to the repository.
  • D : The file, directory, or symbolic link item has been scheduled for deletion from the repository.
  • M : The contents of the file item have been modified.
  • R : The file, directory, or symbolic link item has been scheduled to replace item in the repository. This means that the object is first deleted, then another object of the same name is added, all within a single revision.
  • X : The directory item is unversioned, but is related to a Subversion externals definition. To find out more about externals definitions, see the section called “Externals Definitions”.
  • ? : The file, directory, or symbolic link item is not under version control. You can silence the question marks by either passing the --quiet (-q) switch to svn status, or by setting the svn:ignore property on the parent directory. For more information on ignored files, see the section called “svn:ignore”.
  • ! : The file, directory, or symbolic link item is under version control but is missing or somehow incomplete. The item can be missing if it's removed using a non-Subversion command. In the case of a directory, it can be incomplete if you happened to interrupt a checkout or update. A quick svn update will refetch the file or directory from the repository, or svn revert file will restore a missing file.
  • ~ : The file, directory, or symbolic link item is in the repository as one kind of object, but what's actually in your working copy is some other kind. For example, Subversion might have a file in the repository, but you removed the file and created a directory in its place, without using the svn delete or svn add command.
  • I : The file, directory, or symbolic link item is not under version control, and Subversion is configured to ignore it during svn add, svn import and svn status operations. For more information on ignored files, see the section called “svn:ignore”. Note that this symbol only shows up if you pass the --no-ignore option to svn status—otherwise the file would be ignored and not listed at all!
> svn status --verbose
M               44        23    sally     README
                44        30    sally     INSTALL
M               44        20    harry     bar.c
                44        18    ira       stuff
                44        35    harry     stuff/trout.c
D               44        19    ira       stuff/fish.c
                44        21    sally     stuff/things
A                0         ?     ?        stuff/things/bloo.h
                44        36    harry     stuff/things/gloo.c
> svn status --show-updates --verbose
M      *        44        23    sally     README
M               44        20    harry     bar.c
       *        44        35    harry     stuff/trout.c
D               44        19    ira       stuff/fish.c
A                0         ?     ?        stuff/things/bloo.h
Status against revision:   46

Examing History

svn log

Shows you broad information: log messages attached to revisions, and which paths changed in each revision.

> svn log
> svn log -r123:HEAD
  • Because Subversion allows you to move and copy files and directories, it is important to be able to track path changes in the filesystem, so in verbose mode, svn log will include a list of changed paths in a revision in its output:
> svn log -r 8 --verbose
> svn log -r 8 -v


svn diff

Shows you the specific details of how a file changed over time.

  • compare your working files to the cached “pristine” copies in the .svn area
> svn diff
  • your working copy is compared to the specified revision in the repository
> svn diff --revision 3 rules.txt
  • the two revisions are directly compared
> svn diff --revision 2:3 rules.txt
  • You can also compare the file directly from the repository (without having a working copy)
> svn diff --revision 4:5 http://svn.red-bean.com/repos/example/trunk/text/rules.txt

svn cat

This is used to retrieve any file as it existed in a particular revision number and display it on your screen.

> svn cat --revision 2 rules.txt

svn list

Displays the files in a directory for any given revision.

> svn list http://svn.collab.net/repos/svn
  • Using -v or --verbose, you get detailed list
> svn list -v http://svn.collab.net/repos/svn

Branches and Tags

As mention before, SVN differs from CVS for the revision number system. The revision number is global to the repository, each atomic commit will incremente the global revision.

Then a revision N describe the state of the full repository. The result of svn status -v will show the current revision of the files, and also the revision number of the last commit occurred on each file.

... NEED TO COMPLETE THIS PART ... A branch or a tag, is no more than a copy in the repository of a folder. So this operation is very cheap, this is just a matter of saying this tags is on revision N . ... NEED TO COMPLETE THIS PART ...

Repository layout

We saw than a branch or a tag is technically the same idea. But let's adopt the convention that

  • a branch may contains commit
  • a tag will not contains commit, it is just used to "tag" or to give a "name" to a revision of the repository

Then here is a recommended layout for your repository

/trunk      # for the HEAD 
/branches   # for the various branches, versions
/tags       # for the tags

Trunk will contain the current development branch (alias HEAD), then 'branches' will contain for instance Eiffel_57, Eiffel_58, but can also contain a branch for user, since this is cheap operation, let's do it (You can always delete your branch after).

Here are the steps to create this kind of layout easily:

cd /home/username/SvnDir/repo
mkdir example
svnadmin create example/
svn mkdir file:///home/username/SvnDir/repo/example/project -m "created project"
svn mkdir file:///home/username/SvnDir/repo/example/project/trunk -m "created project/trunk"
svn mkdir file:///home/username/SvnDir/repo/example/project/branches -m "created project/branches"
svn mkdir file:///home/username/SvnDir/repo/example/project/tags -m "created project/tags"
Your repository has now fpr revision:  4
(you can do the same by checkouting a working copy, then add the folders and commit .. 
 this will do the same in only one commit)
You can check your repository with 

svnlook tree example/
 /
  project/
   trunk/
   branches/
   tags/


or even
svn list file:///home/username/SvnDir/repo/example/
  project/
svn -v list file:///home/username/SvnDir/repo/example/project
     3 username               Sep 30 09:14 branches/
     4 username               Sep 30 09:14 tags/
     2 username               Sep 30 09:13 trunk/


Creating a Branch

Nb: to have write access via svn:// please edit the example/conf/svnserve.conf, and change the text to
[general]
anon-access = write

There are two different ways to make a copy. We'll demonstrate the messy way first, just to make the concept clear. To begin, check out a working copy of the project's root directory, /project:


svn checkout file:///home/username/SvnDir/repo/example my_ex
or using the svn:// access protocol:
svn checkout svn://username@svn_svr_address/example my_ex
A    my_ex/project
A    my_ex/project/trunk
A    my_ex/project/trunk/src
A    my_ex/project/trunk/src/test.e
A    my_ex/project/trunk/Readme
A    my_ex/project/branches
A    my_ex/project/tags
Checked out revision 5.

Making a copy is now simply a matter of passing two working-copy paths to the svn copy command:

cd my_ex/project
svn copy trunk branches/branch_username
svn status
A  +   branches/branch_username

In this case, the svn copy command recursively copies the trunk working directory to a new working directory, project/branches/branch_username. As you can see from the svn status command, the new directory is now scheduled for addition to the repository. But also notice the “+” sign next to the letter A. This indicates that the scheduled addition is a copy of something, not something new. When you commit your changes, Subversion will create /project/branches/branch_username in the repository by copying /project/trunk, rather than resending all of the working copy data over the network:

$ svn ci -m "Creating a private branch of /project/trunk."
Adding         project/branches/branch_username

Committed revision 6.

And now the easier method of creating a branch, which we should have told you about in the first place: svn copy is able to operate directly on two URLs.

svn copy svn://username@svn_svr_address/example/project/trunk \
          svn://username@svn_svr_address/example/project/branches/branch_username \
     -m "Creating a private branch of /project/trunk."

Committed revision 6.

There's really no difference between these two methods. Both procedures create a new directory in revision 6, and the new directory is a copy of /project/trunk.

Notice that the second method, however, performs an immediate commit. It's an easier procedure, because it doesn't require you to check out a large mirror of the repository. In fact, this technique doesn't even require you to have a working copy at all.

I would advice the second method, because if case of large folder to "branch", this will avoid copying all the files and folder in your working directory (indeed, often when you create a branch, it is for later or other).

Information.png Note: Cheap Copies : Subversion's repository has a special design. When you copy a directory, you don't need to worry about the repository growing huge—Subversion doesn't actually duplicate any data. Instead, it creates a new directory entry that points to an existing tree.

Working with Your Branch

getting the branch's version

Now that you've created a branch of the project, you can check out a new working copy to start using it:

svn checkout svn://username@svn_svr_address/example/project/branches/branch_username
A    branch_username/src
A    branch_username/src/test.e
A    branch_username/Readme
Checked out revision 6.

There's nothing special about this working copy; it simply mirrors a different directory in the repository. When you commit changes, however, other developers won't ever see them when they updates. Their working copy is of /project/trunk or others. Now you can use this working copy, as any other folder in your working copy. The global revision will incremente the same way, when you commit or other commit. If another user wants to use the branch_username , he can use the svn switch command.

for instance

cd my_ex/project/trunk
svn info
 Path: .
 URL: svn://username@svn_svr_address/example/project/trunk
 Repository UUID: e6f56783-ff01-0410-a399-a959a12a58d5
 Revision: 6
 Node Kind: directory
 Schedule: normal
 Last Changed Rev: 5
 Last Changed Date: 2005-09-30 09:20:13 -0700 (Fri, 30 Sep 2005)

svn switch svn://username@svn_svr_address/example/project/branches/branch_username
At revision 6.

svn info
 Path: .
 URL: svn://username@svn_svr_address/example/project/branches/branch_username
 Repository UUID: e6f56783-ff01-0410-a399-a959a12a58d5
 Revision: 6
 Node Kind: directory
 Schedule: normal
 Last Changed Rev: 6
 Last Changed Date: 2005-09-30 09:27:38 -0700 (Fri, 30 Sep 2005)

Note: The Key Concepts Behind Branches

  1. Unlike many other version control systems, Subversion's branches exist as normal filesystem directories in the repository, not in an extra dimension. These directories just happen to carry some extra historical information.
  2. Subversion has no internal concept of a branch—only copies. When you copy a directory, the resulting directory is only a “branch” because you attach that meaning to it. You may think of the directory differently, or treat it differently, but to Subversion it's just an ordinary directory that happens to have been created by copying.}}

Merging

  • Merging is more or less applying some difference to a working copy. Thus, you always merge on a working copy.


Quick examples from

svn merge -r 343:344 http://svn.example.com/repos/calc/trunk my-calc-branch
U   my-calc-branch/integer.c
svn merge http://svn.example.com/repos/branch1@150 \
           http://svn.example.com/repos/branch2@212 \
           my-working-copy
           
svn merge -r 100:200 http://svn.example.com/repos/trunk my-working-copy
svn merge -r 100:200 http://svn.example.com/repos/trunk

Learn with an example

Create the repository

repository: file:///home/username/SvnDir/repo/example
export MYSVN_DIR=/home/username/SvnDir
(change this value to your own path)

cd $MYSVN_DIR/repo
svnadmin create example/
export MYSVN_URL=file://$MYSVN_DIR/repo/example
(change this value to use the correct url, here we use local access using file:/// ..)

Fill the repository with test files

Create the basic structure .. trunk and branches
svn mkdir $MYSVN_URL/project -m "created project"
svn mkdir $MYSVN_URL/project/trunk -m "created project/trunk"
svn mkdir $MYSVN_URL/project/branches -m "created project/branches"

Add folders and files using a working copy
cd $HOME
mkdir test_svn
cd test_svn
svn checkout $MYSVN_URL/project/trunk proj
mkdir proj/src
cd proj/src
mkdir listing
ls > listing/ls.txt
mkdir dating
date > dating/date.txt
cd ..
svn add src
svn ci -m "adding src files"

Now we will create a branch for src

We want to create a branch
if you want to branch all the trunk
svn copy $MYSVN_URL/project/trunk $MYSVN_URL/project/branches/v1 -m "creating branch for src"

And if you want only the branch the "src" folder (and sub folders)
svn mkdir $MYSVN_URL/project/trunk/src $MYSVN_URL/project/branches/v1 -m "mkdir project/branches/v1"
svn copy $MYSVN_URL/project/trunk/src $MYSVN_URL/project/branches/v1/src -m "creating branch for src"

cd $HOME/test_svn/proj

if you look at the repository :
svnlook tree $MYSVN_DIR/repo/example --show-ids
/ <0.0.r5/601>
project/ <1.0.r5/418>
 trunk/ <2.0.r4/981>
  src/ <4.0.r4/810>
   dating/ <5.0.r4/274>
    date.txt <6.0.r4/84>
   listing/ <7.0.r4/596>
    ls.txt <8.0.r4/407>
 branches/ <3.0.r5/198>
  v1/ <2.1.r5/0>
   src/ <4.0.r4/810>
    dating/ <5.0.r4/274>
     date.txt <6.0.r4/84>
    listing/ <7.0.r4/596>
     ls.txt <8.0.r4/407>

Modify some files in your working copy

(which is for now the HEAD/trunk version)

cd $HOME/test_svn/proj/
date >> src/dating/date.txt
ls > src/listing/proj.txt

svn status
M      src/dating/date.txt
?      src/listing/proj.txt
svn diff
Index: src/dating/date.txt
===================================================================
--- src/dating/date.txt (revision 4)
+++ src/dating/date.txt (working copy)
@@ -1 +1,2 @@
 Mon Oct 17 13:54:45 CEST 2005
+Mon Oct 17 13:58:43 CEST 2005

Let's commit our nice changes

svn commit -m "added new date, and new listing"
Sending        src/dating/date.txt
Transmitting file data .
Committed revision 6.

Oups I forgot to add the new file
svn add src/listing/proj.txt
A         src/listing/proj.txt

svn commit -m "added new listing"
Adding         src/listing/proj.txt
Transmitting file data .
Committed revision 7.

Let's change the log's message of revision 6

(since I first forgot to add the new listing)

Warning.png Warning: to be able to change the log of a revision, you must enable the pre-revprop-change hook on the repository.

cd $MYSVN_DIR/repo/example/hooks
cp pre-revprop-change.tmpl  pre-revprop-change
chmod a+x pre-revprop-change

now we can change logs ... (be careful, there is no revision of svn:log property changes)

echo "added new date" > /tmp/newlog_r6
svnadmin setlog $MYSVN_DIR/repo/example -r 6 /tmp/newlog_r6

or using

svn propset -r 6 --revprop svn:log  "added new date" $MYSVN_URL/project/trunk/src/dating/date.txt
property 'svn:log' set on repository revision 6

cd $HOME/test_svn/proj
svn log -r6 
------------------------------------------------------------------------
r6 | username | 2005-10-17 14:02:22 +0200 (Mon, 17 Oct 2005) | 1 line

added new date

Switch to branch working copy

Ok now, we have a branch "v1", and a main branch "trunk" with new commits If we want to work on the branch itself

You can checkout the branch and work on it:
cd $HOME/test_svn
svn checkout $MYSVN_URL/project/branches/v1 proj_v1
A    proj_v1/src
A    proj_v1/src/dating
A    proj_v1/src/dating/date.txt
A    proj_v1/src/listing
A    proj_v1/src/listing/ls.txt
Checked out revision 7.

cd proj_v1
svn info | grep URL
URL: file:///home/username/SvnDir/repo/example/project/branches/v1

svn log
------------------------------------------------------------------------
r5 | username | 2005-10-17 14:28:42 +0200 (Mon, 17 Oct 2005) | 1 line

creating branch for src
------------------------------------------------------------------------
r4 | username | 2005-10-17 14:28:32 +0200 (Mon, 17 Oct 2005) | 1 line

adding src files
------------------------------------------------------------------------
r2 | username | 2005-10-17 14:28:23 +0200 (Mon, 17 Oct 2005) | 1 line 

created project/trunk
------------------------------------------------------------------------
The other way to do, working on the same file, is just to switch your current working copy to the branch version
cd $HOME/test_svn/proj
(this directory contains, the trunk version)
svn info | grep URL
URL: file:///home/username/SvnDir/repo/example/project/trunk

svn switch $MYSVN_URL/project/branches/v1
U    src/dating/date.txt
D    src/listing/proj.txt
Updated to revision 7.

As you noticed, it will put our working copy in the "v1" branche state
svn info | grep URL
URL: file:///home/username/SvnDir/repo/example/project/branches/v1

And let's merge the changes

  • Now, let's merge one change from the trunk into this branch "v1", for that, as previously precised, you need a working copy of the branch "v1" (to patch the diff into this branch)
at this point, we switched the $HOME/test_svn/proj into branch "v1", so "proj" is a working copy of "v1"
remember, we added a new date into "dating/date.txt"

svn log $MYSVN_URL/project/trunk/src/dating/date.txt
------------------------------------------------------------------------
r6 | username | 2005-10-17 14:30:20 +0200 (Mon, 17 Oct 2005) | 1 line 

added new date
------------------------------------------------------------------------
r4 | username | 2005-10-17 14:28:32 +0200 (Mon, 17 Oct 2005) | 1 line

adding src files
------------------------------------------------------------------------

svn diff -r5:6 $MYSVN_URL/project/trunk/src/dating/date.txt
Index: date.txt
===================================================================
--- date.txt    (revision 5)
+++ date.txt    (revision 6)
@@ -1 +1,2 @@
 Mon Oct 17 14:28:30 CEST 2005
+Mon Oct 17 14:29:37 CEST 2005

At this point, we could save this diff into a patch file, and patch the branch copy.
Or simply using the same usage as "svn diff" command, we can directly merge the difference

cd $HOME/test_svn/proj
svn merge -r5:7 $MYSVN_URL/project/trunk/src/dating/date.txt src/dating/date.txt
U    src/dating/date.txt

svn st
M      src/dating/date.txt

Then, we simply need to commit, or revert if you finaly don't want to merge
svn commit  src/dating/date.txt -m "merge HEAD into branch v1"
or
svn revert src/dating/date.txt

Information.png Note: it is recommended that you use the --dry-run to simulate the merging, this way you will see which files will be changed, added, conflicted...

if you want to merge all differences from "project/trunk/src" into "v1/src"
you can do:
cd $HOME/test_svn/proj
svn merge -r5:7 $MYSVN_URL/project/trunk/src src

Now, let's switch back to the trunk copy:
svn sw $MYSVN_URL/project/trunk
A    src/listing/proj.txt
Updated to revision 8.


Need to be documented

svn:externals properties

client side

config file, and auto-props