Using Git to develop Hydrogen

Hydrogen's master source repository is in Subversion, but it's possible to use git-svn and develop using Git. Git is the Source Code Management (SCM) used by the Linux Kernel, and was primarily written by Linus Torvalds and Junio C Hamano. The primary features are:

* Decentralized: All the history is contained on your hard drive. You can make commits, view logs, and merge branches without having to access the network.

* Excellent Merge Tools: When merging branches, Git has tools that make merging very easy. You can also view and see the merges graphically (using gitk).

* Fast: Git is extremely fast to work with, and most operations appear to happen instantaneously.

But here's the two "you gotta see this" reasons for using Git:

1. Seeing Branches and Merges with gitk:  http://lwn.net/Articles/140350/. Notice that you see when a branch (fork) happens, but also when it's merged back into another tree.

2. It's friggin' fast:

### Viewing logs, 10x faster
###
$ time svn log --limit 5 libs/hydrogen/src/hydrogen.cpp > /dev/null

real    0m1.158s
user    0m0.040s
sys     0m0.036s

$ time git whatchanged -5 libs/hydrogen/src/hydrogen.cpp > /dev/null

real    0m0.124s
user    0m0.028s
sys     0m0.028s

### Switching branches in same working copy 2x faster
###
$ time svn switch http://svn.assembla.com/svn/hydrogen/branches/jackMidi

real    0m5.515s
user    0m1.176s
sys     0m1.016s

$ time git checkout jackMidi

real    0m2.003s
user    0m0.372s
sys     0m0.232s

### Merging branches... priceless
### (examples are from the jackMidi branch)

# First view logs to see what *has and hasn't* been merged...
# Then merge 1001:HEAD from trunk
# Then type this easy-to-remember command:
$ time svn merge --non-interactive -r 1001:HEAD http://svn.assembla.com/svn/hydrogen/trunk .

real    0m15.871s
user    0m0.552s
sys     0m0.300s

$ time git merge trunk

real    0m1.250s
user    0m0.844s
sys     0m0.336s

Using git-svn, you can create a bi-directional link with the Subversion server to where you don't even need to check out a Subversion working copy.

Git Documentation

Here's where you can read lots of docs and tutorials about Git:

Official Site:  http://git-scm.com/
Wikipedia Article:  http://en.wikipedia.org/wiki/Git_(software)
git-svn:  http://git-scm.com/

Note that git-svn is a part of Git.

Getting Started using Hydrogen with Git

First, you need to have git and git-svn installed. Make sure you have a 1.5.x version of Git.

Getting started with a good, full repository with Git can be a little tricky. It's even trickier if you might want to share it with people. If you want, you can wade through the docs and wait through a several-hour checkout of the entire SVN repository.

OR....

You can do this:

  $ cd /dir/where/i/want/it/
  $ wget http://gabe.is-a-geek.org/hydrogen/git-clone-hydrogen.sh
  $ sh ./git-clone-hydrogen.sh hydrogen_git
  $ cd hydrogen_git
  ## Hack away.

It'll take about 3-5 minutes for the 9MB download. After you do this, you will never need to touch that server again. You will only be interfacing with the SVN server.

Making and Committing Changes (Single Branch)

After you've made your changes, commit them LOCALLY like this:

  $ git commit -a

You use normal git commands for whatever you want (EXCEPT merging). You can make more than one commit if you want. When you're done, and you like your changes, push them to the SVN server like this:

  $ git-svn dcommit

That's it.

Updating with the latest changes from SVN

Assuming you are on the master branch, and you are following trunk with it (the default):

  $ git-svn fetch
  $ git merge trunk

Managing a Branch (Simple)

Because you are working with SVN and not raw Git, you must not do a normal Git merge between branches that you plan to commit from. If you do, git-svn will become very confused.

To start a Git branch to track the jackMidi branch:

  $ git checkout -b my_jackMidi jackMidi

From then on, changes you make are just like the previous section. (Code-Commit-Code-Commit-...-dcommit).

According to the git-svn docs, you should do your merges like this:

  $ git merge --squash -m "SVN-like log message" trunk

And this usually works just fine. If not...

Managing a Branch (Complicated Differences)

Sometimes, the changes between trunk and your branch are complex from the point-of-view of the diff command. Examples: Reformatting the source code of a file, then making changes. If someone changes trunk... merging these changes in to your branch will be hard. When Git (or SVN) can't figure it out, you get a Conflict.

Sometimes, you have to resolve the same Conflict every time you merge. It's a real pain. It is possible to use Git's advanced merging tools to reduce your workload. So, if you find yourself in that situation, here's how you can do it. For example, suppose you're working on the jackMidi branch.

Set up this:

SVN trunk branch is called trunk
SVN jackMidi branch is called jackMidi
Git local jackMidi branch is called jack_midi

Like this:

  $ git checkout -b jack_midi jackMidi

Now, set up a merge branch like this:

  $ git checkout -b jack_midi_merge jack_midi

You are now on jack_midi_merge. This branch will be a Git-only branch. Never use it for 'git-svn dcommit'.

Merge the changes from trunk, taking full advantage of Git's merge algorithms:

  $ git merge trunk

This will auto-commit unless there are conflicts. This is OK. Resolve any conflicts and commit the changes.

Now, switch to your real jack_midi branch and make the changes like this:

  $ git checkout jack_midi
  $ git diff --binary jack_midi jack_midi_merge > /tmp/merge.diff
  ### Delete all extra files in w.c.
  $ git clean -x -d -f
  $ git apply /tmp/merge.diff
  $ git add .
  $ git commit -a

I think there's a better way to do that... but this works. We're using a DIFF file to bring jack_midi in line with jack_midi_merge.

Check to make sure that we didn't miss anything, and commit to SVN:

  ### This should not return any messages:
  $ git diff jack_midi jack_midi_merge
  $ git-svn dcommit

Sharing branches and Contributing

Currently, there is nobody to share with. If you have a Git-style patch set to contribute, send it to the mailing list. Or, send a URL to your git repository. Gabriel Beddingfield <gabriel@…> will handle the patch(es).

Changelog

* 2009-04-11 Gabriel M. Beddingfield (Create page)