The vast majority of the projects I have worked on were in some kind of source control. Lately they’ve been in Subversion, but before that most were in CVS. I’ve also worked on a couple projects that were using Microsoft Source Safe (I don’t even know if that’s still around).

Recently, however, I’ve been getting into Git. Git is different from any source control system I’ve used. It’s a distributed source control system which not only gives it a huge work flow advantage in my opinion, but also means you can have repositories without a dedicated server.

The distributed nature

Every coder I’ve ever seen that is working on a project using source control has a work flow like the following:

1) Checkout code locally. 2) Work on code locally trying to add features / bug fixes. 3) If work spans several days then, “update” every day, and try to solve small conflicts with the main repository. 4) When done – commit, and if there are conflicts, resolve the conflicts.

The main, and slightly elusive, point I’ve noticed with this setup is the repository is nothing but a database. All the work, all the code managing is done by the developer and then “pushed” to the repository database when ready.

The developers local copy is really just a branch of the main repository. So why not let the developers local copy have all the rights and privileges to be someone else’s main repository? Git was built with this idea in mind, and the explicit goal of being able to merge all changes back upstream.

What this means in reality, is branching and merging are at the core of git, and I’ve found it to work really well. It lets you test wild ideas with code, and not worry about how you’re going to rollback your changes if you go to far out, and it doesn’t work – if that makes any sense.

Look ma, no server

The other exciting part about git, for me, is you don’t need a server running a process anywhere – you don’t need a git server running somewhere.

Most places I’ve worked I’ve implemented source control, and managing a source control server is time consuming. This is all subjective to the level of funding, number of people on staff, tools available, amount of branching etc, but what if you could just remove the overhead of another service that someone has to manage?

By the way, quick plug, I often use cvsdude.com for my Subversion outsourcing, but even with the tools they offer someone still has to manage the Subversion server (adding users, permissions, the cost).

While I feel you’re insane if you don’t use source control, sometimes running an entire Subversion server is overkill for a project. Writing a Mac OS X widget for example – do you need a full on server, bugzilla, a wiki, and trac hooks for that?

With git, however, you can just put a copy of the repository on a server, and call it your main repository. Done. You can control push access using SSH logins, and if you want to allow anonymous access to the repository, you can make it available over HTTP.

Here is what this looks like, for my notes and if you want to try it yourself:

Get a git repository. Either a new one:

$ mkdir my_cool_project; cd my_cool_project;
$ git-init
$ cp -R [all_my_code_files] ./
$ git add .
$ git commit -a

or copy a whole subversion repository (comments changes and all):

$ git-svn clone -T trunk https://mystuff.com/my_project

Do your stuff

$ write_lots_of_amazing_code.sh
$ git commit -a

Prepare for publish:

$ pwd
/home/guy/my_cool_project
$ git repack -d                                                    
$ git clone --bare -l . /tmp/your-proj.git
$ git --bare --git-dir=/tmp/your-proj.git update-server-info
$ mv /tmp/your-proj.git /home/guy/Desktop

Now upload the your-proj.git folder to your publicly available server. As I said before, if you want to allow anonymous access put it in a HTTP available folder, if you want a private one, put it in your home directory or something.

Turn on the hooks for it to update itself when you “push” your new code changes. (one thing to note here is the server needs to have git installed – sudo apt-get install git git-core on Debian / Ubuntu systems)

$ uname -a
your_server GNU/Linux
$ pwd
/var/www/myrepo.com/your-proj.git
$ git --bare update-server-info
$ chmod a+x hooks/post-update

Now it’s ready to be used as a central server.

To “checkout” the code – really cloning the repository locally:

$ uname -a
your_development_box
$ git clone ssh://[username]@[server]/var/www/myrepo.com/your-proj.git

Then working locally, you commit your changes locally.

$ git commit -a

It is very easy to make branches and merge them back into your local trunk (often named master). Here is an in depth posting on the subject when you are ready.

To update your local repository to the code on the server:

$ git pull

And when you are all set with your local changes and ready to push them to the server:

$ git push

Anonymous checkout:

$ git clone http://myrepo.com/your-proj.git

Last bits

Some things to consider:

  • Git doesn’t work on windows without Cygwin. It works great on Mac OS X and Linux however.

  • There are very few GUI tools for git, you (and your developers) need to be cool with the terminal. (try gitk from the command line)

  • You will have many full copies of your repository floating around. While this is great for backup purposes, it might be bad for some projects.

  • On Mac OS X I think you have to compile Git from source (I did anyway). It’s not hard, but if that scares you…