Getting the most out of Subversion in GNOME
Introduction
Subversion, sometimes known as just 'SVN', is a powerful method of allowing many developers to work on the same source code. It is used extensively within the GNOME project and often proves to be the first hurdle for new developers that are attracted to the GNOME project.
Each developer checks out a copy of the current version of the source code from Subversion and then is able to work on their own personal copy separately from other developers. When they have made changes, they commit them back to the Subversion repository. The Subversion server is then able to merge all the changes that the developer has commit back. Sometimes this merging isn't always successful, the developer is notified and they will have to manually fix any possible conflicts that arise before trying to commit their changes again.
The GNOME project has also set up online browsing of its Subversion repository.
If you would like to track the changes that occur in various GNOME Subversion modules, subscribe to the svn-commits-list mailing list, a high volume, read-only list that receives mail every time somebody checks something into the repository. You can filter mail from this list by the title of the modules you are interested in.
Getting Started
Before getting started, it is useful to remember a key point about GNOME Subversion - it is a developer's work space and has no guarantees that a given project will build right out of the box, or indeed, not dump core on start up.
To check out the latest version of a module, from a shell:
svn co http://svn.gnome.org/svn/[module]/trunk [module]
You should replace [module] with the name of the module you want. If you want the check-out to be put in a folder that is not the same as the module name, specifiy your own folder name instead of the second [module] instance.
Registered GNOME developers will be able to use their SSH key to authenticate themselves to the Subversion server so that they make also commit changes back to the Subversion repositories. They will use a slightly different URL to check out and deal with Subversion modules:
svn co svn+ssh://[login@]svn.gnome.org/svn/[module]/trunk[module]
In this case, if your local login is not the same as your GNOME developer login, you will also need to specify it in the URL.
When the check out has been completed, you will start to notice that many projects in Subversion GNOME contain similar files:
- .svn: This directory is present in every directory of a given module. It contains information about version numbers, where the source code came from, etc.. You can ignore it for all purposes, but you should not delete it.
- autogen.sh: This is a wrapper script around gettextize, intltoolize, libtoolize, aclocal, autoheader, automake and autoconf which you use to start building the module. For example
./autogen.sh --prefix=/usr/local will start the build process checking your system, generating all the necessary Makefiles before you are ready to type 'make' and 'make install'.
- README: This generally gives information about the Subversion module in terms of module requirements, where to report bugs etc..
- HACKING: This file usually specifies the rules [if any] for development in the module.
- MAINTAINERS: This file lists the people who are responsible for the day to day maintenance of the module. Generally these are the people you should send patches to.
Subversion allows you to isolate changes onto a separate line of development, known as a branch. Quite often in GNOME, there are stable and unstable branches of development for a given module - as a result, the main trunk [also known as 'trunk'] may not be suitable for your needs. Stable branches in GNOME Subversion are generally a mixture of lowercase alphabetic and numeric characters separated by dashes ie. of the form:
[module/project]-[MAJOR]-[MINOR]
where major, minor are version numbers. For example:
gnome-2-0 gtk-2-0
In Subversion, branches and tags are simply stored in subdirectories. You can check out a branch using the following command :
svn co http://svn.gnome.org/svn/[module]/branches/[branch name] [local folder]
For a list of the available branches for a given module, construct and view the following URL in your browser:
http://svn.gnome.org/viewsvn/[module]/branches
The following example will check out gnome-utils trunk and 'gnome-2-0' branch, creating 'gnome-utils' and 'gnome-utils-stable' in your current directory
svn co http://svn.gnome.org/svn/gnome-utils/trunk gnome-utils svn co http://svn.gnome.org/svn/gnome-utils/branches/gnome-2-0 gnome-utils-stable
Maintainers 'tag' their module to mark releases in GNOME Subversion. Tags in GNOME Subversion are generally a mixture of uppercase alphabetic and numeric characters separated by underscores ie. of the form
[MODULE]_[MAJOR]_[MINOR]_[MICRO]
where MAJOR, MINOR and MICRO are version numbers. For example
GTK_2_0_6 GNOME_UTILS_2_0_2
For a list of the available tags for a given module, construct and view the following URL in your browser :
http://svn.gnome.org/viewsvn/[module]/tags
Subversion was designed so that whenever there were any changes in the source code, you didn't need to remove your sources and re-check out. The following command syncs up your code with what is stored in the Subversion repository
svn update
When you update, you will notice a letter leading each file that is updated or not. These letters have the following meaning
- U: Updated from the server and sent as a completely new file
- P: Updated from the server and sent as a diff which your client used to patch the file
- A: File was added
- R: File was removed
- C: There is a conflict
- M: File has been locally modified
- ?: File in local repository Subversion knows nothing about.
If you have conflicts, you must resolve these, in general, before being able to rebuild the source code.
Moving Forward
Now that you have successfully checked out a GNOME Subversion module and hopefully managing to build it, you are ready to move forward and become a GNOME contributor.
GNOME contributors send 'patches' [sometimes called 'diffs'] to each other and attach them to bug reports in bugzilla.gnome.org. A 'patch' describes changes in a file. This generally gives you something of the following form
<pre>
Index: gcalc.c
===================================================================
RCS file: /cvs/gnome/gnome-utils/gcalc/gcalc.c,v
retrieving revision 1.41.2.1
diff -u -r1.41.2.1 gcalc.c
--- gcalc.c 12 Aug 2002 22:57:12 -0000 1.41.2.1
+++ gcalc.c 19 Aug 2002 18:37:30 -0000
@@ -33,6 +33,7 @@
gchar *authors[] = {
"George Lebl <jirka@5z.com>",
"Bastien Nocera <hadess@hadess.net> (fixes)",
+ "Joe Bloggs <joe.bloggs@gnome.org>",
NULL
};
gchar *documenters[] = {
</pre>Here you can see the lines added prepended with a '+'. If you had removed [or edited] a line of code, you would have been likely to see a line prepended with '-'. Notice it also shows you the revision of the file you are creating a patch against.
Once you make changes to a given file you can generate a patch very easily using the following command
svn diff [filename] > [patch]
This makes a patch of all the changes between your local changes and the file that currently resides in the Subversion repository.
If you are the one that gets sent a 'patch', then you need to merge that patch into your sources. For this you will need to use the following command
patch -p[n] < [patch]
where n is the number of leading components to strip from the path. This number is relative to where the patch was generated from - you can experiment to get the correct number. If you need to reverse a patch, you can use the following command
patch -R < [patch]
Increased Trust
As you supply more and more patches to a given maintainer, or attach them to bugs in bugzilla.gnome.org, the maintainer may ask you to obtain your own Subversion account to make your own source code check ins.
To apply for your own Subversion account, please read the New Account instructions.
Final Steps
With an increased amount of trust and responsibility, you may even be asked to start maintaining a module within GNOME Subversion - or indeed, one of your own that you may have imported.
One of the first things you will have to perform is to make releases on a given module. The following steps are required, in most cases, to make a release
- Bump up the version number in configure.in file
- 'autogen.sh' and 'make' the source
- 'make distcheck' the source to obtain the release tarball
- Commit the changes
- Tag the release. To tag a given release, the following command is used:
svn copy svn+ssh://[login@]svn.gnome.org/svn/[module]/trunk svn+ssh://[login@]svn.gnome.org/svn/[module]/tags/[MODULE]_[MAJOR]_[MINOR]_[MICRO] -m "Tagged for release x.y.z." where MAJOR, MINOR and MICRO are version numbers.
- Write the NEWS for the module
- Upload tarball onto ftp.gnome.org
Announce the release on gnome-announce-list@gnome.org.
At some point, you might find that it will be necessary to branch your module for a stable set of releases, while continuing development on trunk. Branching is very much like tagging, for example:
svn copy svn+ssh://[login@]svn.gnome.org/svn/[module]/trunk svn+ssh://[login@]svn.gnome.org/svn/[module]/branches/[MODULE]_[MAJOR]_[MINOR] -m "Branched at x.y to allow unstable patches on trunk again."
where MAJOR, MINOR are version numbers and you can decide on a more appropriate commit message.
Quite often you will need to merge code from the trunk to the stable branch - generally for bug fixes that apply to both branches. In this case, you have to be careful what you merge over so as not to merge unstable changes into a stable branch.
To merge a given patch from trunk to a stable branch, where you knew the revision number of the patch on trunk was 123:
svn merge -r 122:123 svn+ssh://[login@]svn.gnome.org/svn/[module]/trunk svn+ssh://[login@]svn.gnome.org/svn/[module]/branches/[MODULE]_[MAJOR]_[MINOR] -m "Backported some cool bugfix to the stable branch."
The above method performs the operation on the server without the need for a local checkout. There are many ways to use 'svn merge'. See Version Control with Subversion for more details.
Sometimes you will be required to reverse a given change made by mistake. If the revision number of the patch that you wish to reverse was 123, you could do this simply by the following command
svn merge -r 123:122 svn+ssh://[login@]svn.gnome.org/svn/[module]/trunk svn+ssh://[login@]svn.gnome.org/svn/[module]/trunk -m "Revert broken patch."
This will reverse the changes made in bringing the source from revision 122 to 123.
See also
