Crabgrass development used to be done through subversion, but this had some short-comings, especially with regards to branching and merging divergent code. As different groups take the crabgrass code and hack their own changes on top of it, we need to have the flexibility and capability to integrate those changes that we want from remote branches without it being prohibitively difficult, which would result in useful work diverging so far that it no longer can be harnessed.

This page discusses how to do this by leveraging the technology of git.

If you have never used Git before, you should first go through the gentle introduction to Git. This will lay the groundwork that the following builds on.

Make a git clone of the master crabgrass repository

You can anonymously checkout the master crabgrass repository by doing the following:

$ git clone git://labs.riseup.net/crabgrass-core.git

This will get you the latest code that is in use. You can use this checkout to do your own work, and then publish it somewhere of your choosing. If you would like to integrate your changes back, then you should let crabgrass developers know that you have some changes to pull, how to get those and which changes.

If you are going to be committing to the master crabgrass repository, then you will need to provide a ssh public key to either elijah, pietro, or micah who can add your key to the repository with write access. Once it has been added, you will be able to clone the repository using this mechanism:

$ git clone gitosis@labs.riseup.net:crabgrass-core.git

Yes, you will use the ‘gitosis’ user here.

Do your normal work, using git

Now that its done, you can go into the crabgrass.git directory that you created, and do regular git commands that you already know so well because you already read the gentle introduction to Git. You can add files, commit them, do branches, etc. and its all done locally.

Tracking another remote branch

While in your crabgrass git repository, do the following to add the radicaldesigns greenchange git repository.

First we add the greenchange git repository as a tracked remote repository, called ‘greenchange’:

$ git remote add greenchange git://github.com/sethwalker/greenchange.git

This is now a remotely tracked repository, but we don’t know anything about it locally, so lets update our remotes:

$ git remote update                    
Updating greenchange
remote: Counting objects: 15742, done.
remote: Compressing objects: 100% (5602/5602), done.
remote: Total 15235 (delta 9221), reused 15093 (delta 9133)
Receiving objects: 100% (15235/15235), 5.41 MiB | 378 KiB/s, done.
Resolving deltas: 100% (9221/9221), completed with 95 local objects.
From git://github.com/sethwalker/greenchange
 * [new branch]      master     -> greenchange/master
 * [new branch]      network_feed -> greenchange/network_feed
 * [new branch]      sphinx     -> greenchange/sphinx

NOTE: Be sure to look closely at what was printed above on your screen. With the greenchange repository you will most likely run into a “warning: no common commits”. If you see this message, then you will generate git commits out of our upstream subversion repository that are fundamentally different from the other repository and git will not be able to associate them as being the same. This will create way more confusion in your history and make pulling things from their repository impossible. However trying to fix this turned out to cause all kinds of problems, so the crabgrass git repository was made in a way that probably would not have common commits with that greenchange repository.

Check that out… we pulled in the greenchange remote repository references, it made available all the history of the greenchange ‘master’ branch, and it also pulled in two other branches that they have going ‘network_feed’ and ‘sphinx’.

Lets have a look at what we have in our current git repository:

$ git branch
* master

So this shows us we still just have our main branch, thats because remote repositories aren’t local branches, until we actually create a local one off of the remote branch. We’ll do that in a minute.

We can see what remote branches we have by passing the -r option to git branch:

$ git branch -r
  greenchange/master
  greenchange/network_feed
  greenchange/sphinx

Understanding what happened in the remote branches

Ok, awesome, we have a local git repository, we are tracking the remote radicaldesigns git repositories. What would be really interesting is to fire up gitk --all and see how their branches have diverged from ours, when and pull things from them as we see fit.

If you run gitk --all you can look through the history and holy moses this looks like a complicated subway map! Lets try and find out at what point they branched off of our repository. Scroll way down to the very bottom, you see the first svn commit on 2006-11-30. You can browse through this history by going up to 2007-11-08 where you will find a commit with SHA1: 268db1db403580b68c85cc3d85b58e 6efb57756f, this is where seth created a greenchange branch in subversion. If you look at the commit right before it that abie made (fa825dd909d0fb3d8244fecce8801b 95314f2179) you see:

Parent: 7de6aca3a898766fc3dc2dd3552f655322656ee8 (embed the svn revision number in the footer)
Child:  fdc2c0e08397825ae084da1923dddf795261dac5 (delete assets off a page)
Child:  268db1db403580b68c85cc3d85b58e6efb57756f (creating a greenchange branch)
Branches: master, remotes/git-svn, remotes/greenchange/master, remotes/greenchange/network_feed, remotes/greenchange/sphinx
Follows: 
Precedes: 

    added ruby-svg lib to vendor/plugins, and include it in group_controller
    
    
    git-svn-id: http://code.autistici.org/svn/crabgrass/trunk@612 4da624d7-9686-4b4d-bf4a-96ca807925bb

In this particular commit, there are two children, one is where the subversion trunk continued, and one is where the greenchange branch continued. You can click on each of those SHA1 hashes to see where they go, or you can also click on the tip of the little green arrow to see where it resumes. Anyways, if you follow the greenchange branch up you will probably come to the conclusion that seth was using git-svn to interface with the crabgrass subversion repository.

Somewhere up there in the big tangle of colored lines you can see seth moving to github as his upstream published source, and he stops updating the subversion repository (around 03-12-08).

Cherry picking changes

You might be browsing through various remote branches with gitk --all and see a changeset that you want in the branch you launched gitk from. Simply right-click on the changeset and choose ‘cherry-pick this commit’, it will try to pull that commit into your branch and if there are no conflicts it will add it into your repository. You can also generate patches from the different commits. You can also do ‘git cherry-pick’ on the command-line to apply a change that a particular commit introduces in another branch and record that new commit in your local branch.

Deploying with git

You can use capistrano with git. If you are moving from subversion to git you will want to take a look at your deploy.rb that you have been using with crabgrass. It will have a :repository URL that has the subversion repository, and your scm will probably be set to subversion (set :scm, :svn). Replace the repository with the git URL and set the scm to git (set :scm, :git). Thats all you need to do to get git deployments to work in capistrano!

You do have to make sure that you can ssh to your server and run git clone it should work without problem.

You might also want to add “set :deploy_via, :remote_cache”, because by default git will do a clone every time instead of the equivalent of a svn export, as there isn’t really such a thing in git, so setting this will do clone the first time, and then just runs a fetch every time after that. You can also set a particular branch in capistrano (maybe you have a production branch that you want to use for deployment), ‘set :branch, “production”’ would set the branch to production.

Submitting patches to crabgrass

Draft

How do you submit a patch to crabgrass?

  1. First clone the main git repository as described above
  2. Go into that directory and make your changes
  3. Run
    $ git format-patch origin/master --stdout > fixedittaskbug#4324.patch
    
  4. Attach that patch to the bug system
  5. Someone else can then download that patch file and then run ‘git am’ to apply it to their repository:
$ git am < fixedtaskbug#4324.patch

Known Issues

If you run into a

command not found: git-config --get user.email

you probably use git 1.6 where the git-dash commands have been removed.

Check the line the error was raised like ‘active_support/inflector.rb:283’ and replace ‘git-config’ to ‘git config’ in your install of active support.