Talk @ 2: Using GIT for Rails Development
16 Aug 2007
A few weeks ago we start experimenting with Git for Rails development.
I am not going to highlight the all of the advantages of using git here, but let me mention that Git is one of the few SCM out there that really understands merges.
As Linus, the creator of git, says “in this thread”:http://www.gelato.unsw.edu.au/archives/git/0504/2182.html bq. “The important part of a merge is not how it handles conflicts (which need to be verified by a human anyway if they are at all interesting), but that it should meld the history together right so that you have a new solid base for future merges. In other words, the important part is the trivial part: the naming of the parents, and keeping track of their relationship. Not the clashes. And it looks like 99% of SCM people seem to think that the solution to that is to be more clever about content merges. Which misses the point entirely.”
Git tracks content, not files. Git is really a filesystem, represented by tree structures. So you are really comparing trees between commits, and tracking the changes of the nodes in the tree.
There are enough tutorials out there for you to start grasping git. I can recommend these ones:
- “Beginners tutorial”:http://www.kernel.org/pub/software/scm/git/docs/tutorial.html
- “Git user manual”:http://www.kernel.org/pub/software/scm/git/docs/user-manual.html
- “Git for SVN users”:http://git.or.cz/course/svn.html
You may want to consider Git if you have ever run into a merge marathon on a big project with SVN. If you have ever tried it, it is just painful and it does not work, not the SVN way.
h3. Enter Git
Git makes branches easy to create and merge. Git branches are only a 40-digit hex hash, with the origin of the branch. Branches are cheap, and easy. You start using git, and before you realise it, you are merging and branching all the time.
So a regular working pattern would be:
------------------------------------
git branch mywork
git checkout mywork
...hack some files (file1 file2 file3)...
git add file1 file2 file3
git commit
git checkout master
git merge mywork
------------------------------------
Yes that’s good, but what happens when all your development repositories are under SVN control? Well here comes a little script that will help us integrate with our existing repositories.
h3. Enter git-svn
git-svn is a little perl script (that comes bundled with the Git distribution) that lets you track SVN repositories. You can also commit back between Git and SVN. This is very good, you can start using git without converting your working repositories yet… well until you are ready to migrate them.
h3. GIT RAILS RECIPE
mkdir beast
cd beast
git-svn init http://svn.techno-weenie.net/projects/beast/trunk (for example)
git-svn fetch -r2940 (get a particular repository revision)
git-svn fetch ( get the whole repository history)
then REPEAT{
git checkout -b mywork (start my own branch)
....START HACKING (fix some bugs)
git commit -a (commit the changes to git)
git checkout master (switch to master branch)
git-svn rebase (update master with the upstream svn repository)
git checkout -b mymerge (create a branch mymerge and checkout from master)
git merge --squash mywork (merge into current branch, mywork branch)
git commit (commit the changes to git)
git-svn dcommit (commit the changes to svn repository....if you have enough permissions)
git checkout master (switch to master branch)
git-svn rebase (update master with the upstream svn repository again)
git branch -D mywork mymerge (get rid of branch mywork and mymerge)
}
See http://cheat.errtheblog.com/s/gitsvn/ for a cheat sheet on this.
Here James Bowes tells us why rebase is important: http://jbowes.dangerouslyinc.com/2007/01/26/git-rebase-keeping-your-branches-current/
There is one problem with git-svn. It can not handle svn:externals yet.
But there is a workaround to it. Once you fetch your RAILS svn project, you may want Rails edge in your vendor directory, or some handy plugins as well.
Get RAILS EDGE into a separate git clone as well as your handy plugins. Then do a symlink into the vendor directory.
mkdir rails_edge
cd rails_edge
git-svn init http://svn.rubyonrails.org/rails/trunk (for example)
git-svn fetch -r7300 (get just the latest revision you know about)
git-svn fetch (perform a fetch once in a while to keep it up to date)
then cd myproj/vendor
ln -s ../../rails_edge rails
Perform the same task for every plugin you use. You may also track a stable version of rails like http://svn.rubyonrails.org/rails/branches/1-2-stable
There are pros and cons of this approach. You can decide if this is enough for your current needs or wait until git supports subprojects. Keeping Rails stable and edge in different repositories, and tracking their changes independently seems to be a very clean way to work.
I hope that gives you a warm welcome to the world of git, and that you start enjoying Rails development along with Git.
