Subsections
In true Perl spirit there are more than one way to perform the below
tasks. It is also assumed that the subversion repository is residing on a
server (here, svn.example.com is running a web server with svn
support), and calc is used as
the example project. Furthermore, since we are anticipating branching
of the project, we must prepare our repository for branching. Command
examples are typed as
command --with-option example
and
sample
output is typed like this
Setting up a new personal repository is straight forward, do
svnadmin create /path/to/svn/repos/project
and subversion is now
ready accept addition of projects into the repository. If the
repository resides on a server, then you need access to server and do
some more initialisation steps (see Appendix E.1).
If the repository is empty (still at revision 0), you start by
creating the initial directory structure to be imported into the
repository, and (optionally) add files to be imported.
mkdir /tmp/myproject/branches
mkdir /tmp/myproject/tags
mkdir /tmp/myproject/trunk
cp ...
Import the project with
svn import /tmp/myproject http://svn.example.com/calc -m
"Initial import"
Subversion does not store the root name
/tmp/myproject, so these are only temporary names.
Assuming we want to checkout the main trunk of the project a simple
svn checkout http://svn.example.com/calc/trunk calc
will
do. This will create a sub-directory calc containing the latest
revision of the project.
There two ways to set your favourite text editor for log message
editing. Either you define it in the config file, or set one of
the environment variables SVN_EDITOR, VISUAL,
or EDITOR to point at your preferred editor. svn
will use the first one it finds in the order we described the different
possibilities here.
If we realize that a change committed to the repository is unwanted
we can reverse these by reversing the order of revisions;
svn merge -r 303:302 http://svn.example.com/calc/trunk
Check the changes, and commit if you are happy with them. Magic!
Sometimes we forget that adding items to subversion control is a
recursive action, and as consequence end up with a huge import of
files. The easiest way out of this is to use the revert sub-command
svn revert item
where item is whatever you added (or item can be empty, and everything
in the current directory will be reverted). Note, this will actually
revert all uncommitted changes not just whatever you added.
For this the best solution is to use svn copy
as
svn copy -r 807
http://svn.example.com/calc/trunk/real.c ./real.c
The added bonus
with this is that subversion will also
remember the file history.
You can also set what files svn should ignore when running
svn status in the config file (see
Appendix F).
Yes, subversion handles symbolic links (in operating systems where
these make sense) automatically, just treat them as any other item.
A..10 Creating a branch
The simplest way to create a branch is to make a copy of the current
trunk HEAD (or another revision in the tree) by issuing
svn copy http://svn.example.com/calc/trunk
http://svn.example.com/calc/branches/my-calc-branch
-m "Creating a private branch of /calc/trunk."
This will create a shallow copy, meaning that subversion
creates links within the repository until files are actually
changed. In consequence branches are inexpensive, and you should not
be afraid to create branches. You have to check out the new branch to
get access to it. The changes needed to the above command when
creating a branch from a tag is straightforward.
You can also create branches within your checked out project (see more
in the svn book). There are no real branching in subversion, there are
different directories with files that share a common history. Branches
is an attribute that the users of subversion attach to the branches
directory.
Sometimes you want to copy changes between branches and this is is
accomplished by merging different revisions. Issuing
svn
merge -r 343:344 http://svn.example.com/calc/trunk
will perform a
local update of your branch using the difference between the revision
specified. You should review the changes before committing them into
your repository branch. If something went wrong or is unsatisfactory,
use svn revert. However, revert may not be able to perform
well in some cases.
Assuming we have a branch that only contains change sets from the
branch itself, i.e., no change sets have been ported from trunk to the
branch. Now we want all changes made to the development branch to be
ported into the main trunk. To accomplish this we need an up to date
working copy of the main trunk. The procedure
is
cd calc/trunk
svn update
At revision 405.
svn merge
http://svn.example.com/calc/branches/my-calc-branch
-- Merging r336 through r405 into '.':
...examine the diffs, compile, test, etc...
svn commit -m "Merged my-calc-branch changes into
the trunk."
Committed revision 406.
where some output has been removed. Note that only changes committed
into the repository are available for porting. At a later point when
more development has occurred in the stable branch, we want to port
these changes as well. This is equally easy since the repository
remembers which change sets have already been merged into the main
trunk, and the the procedure is simply
cd calc/trunk
svn update
At revision 513.
svn merge
http://svn.example.com/calc/branches/my-calc-branch
-- Merging r406 through r513 into '.':
...examine the diffs, compile, test, etc...
svn commit -m "Merged my-calc-branch changes into
the trunk."
Committed revision 514.
Having a feature branch, it is recommended to keep it in sync with the
trunk, i.e., port changes in trunk into the feature branch.
cd branch-working-copy
svn merge http://svn.example.com/calc/trunk
The repository knows when the branch was created from the trunk and
will only merge change sets added to the trunk after the branch was
created. After some time there has been some significant development
in trunk and you want to port these to the feature branch. This is as
easy as before
cd branch-working-copy
svn merge http://svn.example.com/calc/trunk
-- Merging r354 through r501 into '.':
and you do not need to worry that changes will be ported twice. The
repository remember which change sets have already been merged to the
branch and will not merge these again.
Assuming that you followed the convention of keeping your feature
branch in sync with the trunk, all that is needed is
cd trunk-working-copy
svn update
At revision 1910.
svn merge --reintegrate
http://svn.example.com/calc/branches/my-branch
--- Merging differences between repository URLs into '.':
Please note the use of the reintegrate option, which is critical. It
tells subversion that your feature branch is a mixture of trunk
change sets and branch change sets. With the reintegrate you have
asked subversion to carefully find the branch change sets and only port
these.
Now when your feature branch has been merged into trunk it is
recommended to remove the branch because the branch is no longer
usable for further work. It would not be capable of correctly pick up
change sets from the trunk via an svn merge, nor can it be properly
reintegrated into trunk again. If you need to work further on the
feature branch it is better to destroy it and create a new branch.
If you have been a bad boy and as such, out of sync. You
must start by porting all changes made to the trunk into your branch
and then you are ready to perform the merge into the trunk.
When a branch has become obsolete this can be removed
with
svn delete
http://svn.example.com/calc/branches/my-calc-branch
-m "Removing obsolete branch of calc
project."
A deleted branch can be resurrected if needed.
If we want to create a snapshot of the trunk exactly as it looks like
in the HEAD revision, just make a copy of it
svn copy http://svn.example.com/calc/trunk
http://svn.example.com/calc/tags/release-1.0
-m "Tagging the 1.0 release of the 'calc'
project."
assuming you followed the guidelines and created a tags
directory in you initial import. Use -r if you prefer to
specify a revision to tag.
Remember rule 2.1.9; Do not mess with the tags
directory. If you need to change a tagged revision of the
project, you need to make a branch using the tags structure as
template for the branch (see item A.10).
You can create a tag with your current working copy status
ls
my-working-copy/
svn copy my-working-copy
http://svn.example.com/calc/tags/mytag
Why is this here? There is one (at least) interesting
use for this feature. Sometimes there are situations where you have a
bunch of local changes made to your working copy, and you'd like a
collaborator to see them. Instead of running svn diff and sending a
patch file (which won't capture tree changes), you can instead use svn
copy to “upload” your working copy to a private area of the
repository. Your collaborator can then either checkout a verbatim copy
of your working copy, or use svn merge to receive your exact changes.
This is straightforward use of the svn list command
svn list http://svn.example.com/calc/tags
Remember rule 2.1.9; Do not mess with the tags
directory. If you need to change a tagged revision of the
project, you need to make a branch using the tags structure as
template for the branch (see item A.10).
Sometimes the location of a repository changes, but the contents of
the repository stays the same, i.e., the URL to the repository is
changed. A repository move is easily fixed with the svn
switch command, this will change the URLs in your working
copy. No file contents are changed, and your work is untouched and can
be committed to the new location after switching to the new URL. This
is subversion magic. Here is an example where a repository moved from
svn.example.com to new.host.org:
svn switch --relocate http://svn.example.com/calc
svn://new.host.org/repos/calc .
We changed server type and directory path in this example. The
Subversion Book warns about spelling errors when changing the URL
since it may cause havoc for you, so be careful out there.
A..20 Change trac ticket status through commit log messages
There may be post-commit hooks in the subversion repository that
performs specific tasks when changes are committed to the
repository. One of these utility programs performs status changes to
trac
tickets if the log message is properly formatted. The
trac-post-commit-hook searches commit messages for text in
the form of:
command #1
command #1, #2
command #1 & #2
command #1 and #2
where command is one of
closes, fixes
The specified issue numbers are closed with the contents of this
commit message being added to it.
references, refs, addresses, re
The specified issue numbers are left in their current status, but
the contents of this commit message are added to their notes.
closes and fixes are synonyms, and
references, refs, addresses, and
re are all synonyms. More than one command can be issued in a
message. An example message is “Fixes #10 and #12, and refs
#13. Changed blah and foo to do this or that.” This message will close
tickets 10 and 12, and add a note to ticket 13.
Note, it is important that #number is used, i.e., ticket:number will
not work.
Information on where to retrieve and install the
trac-post-commit-hook is available in
Appendix E.3.