/!\ Attention: GNOME moved to the Git source control system, please see Git. This page is obsolete, as it deals mostly with the use of git-svn.

Git for GNOME svn developers

Git is the revision control system used for the Linux kernel, Xorg, Freedesktop projects, Cairo, and many other projects. This page documents how you can use Git to do GNOME development.

DISCLAIMER: This page is NOT about switching GNOME to use Git instead of Subversion. Do not even comment about that here; it's not the right place to do it. This is about using Git in conjunction with GNOME's existing infrastructure.

See also Shaun's basic Git workflow: part 1 and part 2.

Why Git?

Roughly in order of importance / convenience:

How do I use Git to hack on an existing GNOME project?

As of January 2007, GNOME uses Subversion as its revision control system. Fortunately, Git has good tools to let you use a SVN repository as the "mothership" while you enjoy most of Git's features on your own computer.

Please use Git 1.5 or later.

Cloning a GNOME repository

The easiest way is to use GNOME's own git-mirror. You can start working on a repository like this:

git clone git://git-mirror.gnome.org/git/modulename
cd modulename

Since all gnome modules have a common url prefix, it can be convenient to set up an alias:

git config --global url.git://git.gnome.org/git/.insteadof gnome:

Then modules can be grabbed by doing this:

git clone gnome:modulename
cd modulename

To be able to use the git checkout to also interact with the current subvesion trees, you need to setup the git tree to use git-svn. For write access to the current subversion setup, you can run:

git svn init -s svn+ssh://svn.gnome.org/svn/modulename --prefix=origin/svn/
git svn rebase

If your username is not the same as the one used to login to your computer, you will need to change the SVN URL like this:

git svn init -s svn+ssh://username@svn.gnome.org/svn/modulename --prefix=origin/svn/

If you do not have write access to the subversion repositories or want a readonly interface to the subversion repositories, run:

git svn init -s http://svn.gnome.org/svn/modulename --prefix=origin/svn/
git svn rebase

This gets the initial clone from GNOME's git-mirror, and then uses git-svn to quickly populate all the information required by git-svn.

Getting updates

Once you have cloned a repository, you'll want to update it periodically from upstream's changes. You can simply do this:

cd modulename
git svn fetch
git svn rebase

You can of course do "git fetch" on individual branches, or use Git's features normally.

Doing local development

The cardinal rule of doing development with Git is: don't use the master branch. Think of the master branch as the "pristine copy" of upstream's sources.

Create a branch:

cd modulename
git checkout -b mybranch

This creates a branch starting from wherever you are, which at this point usually means "HEAD in the master branch".

With Git it is customary to do many small, logical commits, instead of big commits which modify many things at once.

Modify some files:

emacs file1.c file2.c ChangeLog

Mark them and commit them:

git add file1.c file2.c ChangeLog
git commit -m "Colorize the frobs in funny ways"

Note you need to tell Git what to commit: the "add" and "commit" steps are separate. This is useful when you need to keep a modified file around but not commit it just yet.

Merging your branch and committing to SVN

Once you are finished with your work in mybranch, you'll want to merge it to your master branch (remember, that's the one which tracks the upstream SVN repository) and then actually push the changes to SVN.

Switch to your master branch:

git checkout master

Merge the changes from your branch:

git merge --squash mybranch

IMPORTANT: The --squash option is important. Git keeps information about what got merged where, but SVN doesn't. Git-svn cannot handle "normal" merges as done with Git; the --squash option tells "git merge" to act as if this were a manual commit, not a merge (more info). Notice that in the upstream Git repo some patches which would allow git-svn to use a real merge instead of the faked one with --squash are already included (Link to Git commit).

Commit the changes:

git commit -a -m "Merge mybranch into the master branch to implement feature X"

Finally, send the changes to the SVN repository:

git svn dcommit

Using git with jhbuild

JHBuild has support for using git to manage svn and cvs repositories. To enable this support add the following to your .jhbuildrc file:

svn_program = git svn
cvs_program = git cvsimport

This will then cause jhbuild to check out cvs and svn repositories using git, from the current revision. If you want the full development history you need to checkout the module as described above.

Note: This will not convert existing cvs/svn checkouts to use git and thus requires you to manually delete any existing svn/cvs checkouts before using this feature

Sending patches

Git encourages you to do many small, self-contained commits. For example, say you want to add a feature to a program, but first you need to refactor the code a bit to allow your feature to fit in. A first patch would do just the refactoring. A second patch would actually add your feature. A third patch would update the documentation. If your feature is very complex, you may want to add stub functions in a commit, then actually fill them in in further commits, etc.

The idea is to submit small patches for review by maintainers, instead of burdening them with the information overload of a single mega-patch.

Let's say you created a branch mybranch off the master branch. Hopefully this is not your original work branch, but instead a "cleaned up" branch with actual logical commits, which you would be proud to show to your mom, instead of experimental / "fix whitespace" / "remove debug printf" commits that you had in the work branch. You have several commits in that branch. If you are in mybranch, you could generate a patchset like this:

mkdir ~/patchset
git format-patch -n -o ~/patchset master

This will create ~/patchset/0001-xxx.patch, ~/patchset/0002-yyy.patch, etc., for all the commits in your branch. Each file is intended to be a separate mail message which contains your commit message, a diffstat, and the actual patch. These files are in Unix MBOX format; you can import them into Evolution or your mailer of choice to send them out to the maintainer. If you import them in Evolution, you can then select "Edit as new message" from the context menu of one of those mails to enter the To: header and actually send out the mail.

If you want to attach a patch or an entire patchset to GNOME's Bugzilla, you can use the most excellent git-send-bugzilla script written by Steve Frécinaux. This Perl script will attach a set of commits as single patches, complete with commit message and diffstat, to a bug given its number.

Full repository checkouts

GitForGnomeDevelopers (last edited 2009-04-24 10:58:26 by MurrayCumming)