Archive for September, 2008

Backpack Picnic: Farmer Dinner

Monday, September 22nd, 2008
Farmer Dinner

A comedy group I’ve gotten into recently has a show called Backpack Picnic that can be found on the ON Networks site. If you’re looking for something new/funny/smart, check them out.

My favorite episode so far is called “Farmer Dinner,” in which a genius farmer son named “Ma jr.” argues with his farmer dad about the physical definition of work until they’re interrupted by “Pa jr.” who has just returned from returned from his new life as a fisherman. What could be funnier than that?

Multiple Remote Git Branches With Different Local Names

Sunday, September 21st, 2008

I pounded my head against the wall for a bit when trying to play out this scenario in Git:

  • Remote repository has two branches: master and some-long-complex-name
  • Locally, I have cloned master
  • I have set up my config to refer to the remote master as “origin”
  • I have checked out some-long-complex-name using the following:
$ git checkout --track -b simple-name origin/some-long-complex-name

The key thing to note is that my local branch has a different name than the remote branch, i.e., “simple-name” is my local branch that’s tracking the remote branch “some-long-complex-name”.  I’ve used pseudo-branch-names in this example, but in practice I like my local branch names to be 3 characters or so such that they’re easy to type, and I like the remote branches to have long names such that there is no ambiguity about what they are.

My initial .git/config looked like this after the aforementioned checkout command:

[remote "origin"]
        url = ssh://myserv/srv/git/proj.git
        fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
        remote = origin
        merge = refs/heads/master
[branch "simple-name"]
        remote = origin
        merge = refs/heads/some-long-complex-name

Now, this isn’t too bad.  All pull related commands work, but push only works for the master branch.  What I wanted was git to push to “some-long-complex-name” whenever I ran “git push” from my local “simple-name” branch.

I changed .git/config to look like this:

[remote "origin"]
    url = ssh://myserv/srv/git/proj.git
    fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
        remote = origin
[remote "simple_origin"]
        url = ssh://myserv/srv/git/proj.git
        fetch = +refs/heads/*:refs/remotes/origin/*
        push = simple-name:some-long-complex-name
[branch "simple-name"]
        remote = simple_origin
        merge = refs/heads/some-long-complex-name

Note the additional “remote” section and the “push” reference.  Now, when I’m in my simple-name branch, I can just type “git push” and this branch will push out to the remote branch names “some-long-complex-name”.

Thanks to those who offered help on the freenode IRC #git channel, namely RandalSchwartz.

College Reporters on Facebook Style Change

Saturday, September 20th, 2008
Reporters

I like the Internet. I like web sites. I spend significant hours of my life with my computer. (I view it as my slave, forced to do my hardest work. But that’s another post.) Despite all of my time and interest, I don’t get the social networking fanatics. I saw an iReport video on CNN about some kids trying to petition the new style and layout on Facebook and I couldn’t help but think, “what?” (Seriously, watch it.)

Is it just me, or were you thinking, “college student?” when that second guy came on? And what about the first kid? He seems like he should be joking, but he’s not. Best of all is when they start talking about the attention the college kid has now with his group. The college kids says it’s annoying because people disagree with him. Ah, a good ol’ dose of reality. Some advise for this kid: when you protest a $15B company’s actions, don’t expect it to be easy. You might actual have to *gasp* work to get what you want if you feel it’s that important.

On the flipside, I hope it works out for him. I hate the new Facebook layout too.

Installing Gitweb on Fedora Linux and Apache

Friday, September 19th, 2008

My next natural step after getting my projects up and running with Git was to install a web interface. Gitweb was my choice because:

  • it’s available via yum with Fedora
  • it provides up-to-date diff information
  • it’s part of the overall Git package, so it’s tightly integrated

Installation was ultimately quite simple, but I found the install docs to be less than helpful for people like me who want immediate functionality and will get to the tweaks and details later.

Step 1: Install Gitweb

sudo yum install gitweb

This will install a few files at /var/www/git.  You shouldn’t need to do anything to them.

Step 2: Create /etc/gitweb.conf

You need a configuration file to tell Gitweb where to look for your project.  You can change this folder to wherever your project will be.

$ echo "\$projectroot = '/srv/git/';" > /etc/gitweb.conf

Step 3: Edit Apache Configuration File

This configuration file assumes you are running your site as a virtual host.

/etc/httpd/conf.d/git.conf
  1. <VirtualHost *:80>
  2.     DocumentRoot /var/www/git
  3.     ServerName git.yourproject.com
  4.      <Directory /var/www/git>
  5.           Allow from all
  6.           AllowOverride all
  7.           Order allow,deny
  8.           Options ExecCGI
  9.           <Files gitweb.cgi>
  10.                SetHandler cgi-script
  11.           </Files>
  12.      </Directory>
  13.      DirectoryIndex gitweb.cgi
  14.      SetEnv  GITWEB_CONFIG  /etc/gitweb.conf
  15. </VirtualHost>

Step 3: Tweak Your Repository’s Config File

Gitweb lists two key elements at the start of your project’s page: description and owner.  To have these display something appropriate, edit /srv/git/yourproject/.git/description:

My Awesome Project

… and add this to /srv/git/yourproject/.git/config:

[gitweb]
        owner = "Mark McBride"

Step 4: Restart Apache

That’s it.  Just restart Apache and you should find Gitweb running at the domain you’ve specified.

References:

Migrating a Subversion (svn) Project and Server to Git

Wednesday, September 17th, 2008

I’m sold on Git. The branching feature alone was reason enough for me to move from Subversion. However, the decision to move was the easy part. Migrating my projects, while not too painful, wasn’t trivial. I found that my knowledge of svn was actually a disadvantage as it made it easy to assume things about Git that simply weren’t true. This is ultimately how I went about my migration.

First, some assumptions:

  • My projects are small. By small I mean that everyone working on code has shell access to the servers involved. It’s not open sourced, public, or any of that cool stuff. If you need to do something for large scale access, consider GitHub or gitosis.
  • I have a semi-centralized need. None of the people on my projects are co-located. There is a definite need for a place to post code for review that everyone can access.
  • I have a functioning, in-production Subversion repository and the transition must be seamless.
  • My apps are Rails applications deployed using Capistrano.
  • All of my servers/clients are running Fedora 9
  • You understand the basics of Git.

That said, let’s dive in.

Step 1: Install Git

This is the easy step:

[local]$ sudo yum install git git-svn

Step 2: Convert your Central Subversion Repository to a Local Git Repository

This is key step to wrap your mind around conceptually. With svn you would first make a central repository and import something into it to get started. We’re about to do quite the opposite. Remember that in Git every instance is a repository. When we grab the contents of your existing project, we will be building the new repository locally, not on your server (that will come later).

Build a text file list of your existing authors

In order to maintain some continuity with your existing svn logs, we need to peg the svn user names of people who have committed to your svn repository to git user names. This is quite easy to do. Just create a text file with lines that look like this:

markmcb = Mark A. McBride <mark@markmcb.com>
example = Example Person <person@example.com>
... etc.

Save this file. I’ll refer to it later as svn-to-git-authors. (If you have a lot of authors, check out Josh’s script to automate the creation of this file.)

Clone your Subversion database to a Git repository

This next step is so nice. With one command and the help of the file we just created, we’ll create an almost ready to use git repository. The command is simple: git clone “what” “where”. Or something like:

[local]$ cd /path/of/your/liking
[local]$ git svn clone svn+ssh://yourserver.example.com/path/to/your/repository \
             ./myrepos.git --authors-file=svn-to-git-authors

Hit return and relax as the magic happens. Depending on the size of your repository, this could take some time.

Set some basic configuration options

There are hundreds of configuration options for Git, but I’m only going to touch on a few critical ones. Specifically, let’s tell our new Git repository who we are and set the stage for working with a remote, semi-centralized repository.

[user]
name = Mark A. McBride
email = mark@markmcb.com

The user settings are pretty straightforward. Just ensure they match what you had before in the authors file and it’ll be very easy for you to keep track of who has done what. In addition, you may see a section relating to svn. Once you no longer need to pull data from that repository (which, unless your repository is busy, is right now), you can delete this section.

From here you’re ready to get to work. You have a functional repository. However, if you plan to work with anyone other than yourself, you may need to interact with a public repository.

Step 3: Setup a Public Repository

The steps to establish a repository that you can access over ssh are pretty simple. Just ssh to the public server and (you may need to setup permissions to write depending on the folder do the following in):

[publicsrv]$ cd /srv/git
[publicsrv]$ mkdir publicproject.git
[publicsrv]$ cd publicproject.git
[publicsrv]$ git --bare init

That’s all you need to do on the server. The critical thing to note is that bare reference. This tells Git that there is no working copy, i.e., the files you are coding. All this repository will track are the changes and not actually store the files (though anyone can clone this repository and get the files).

Point Your Repository to the Public One

Back on your local machine, you just need to run one command to make your repository aware of this newly created public version:

[local]$ git remote add origin ssh://publicsrv.example.com/srv/git/publicproject.git

Now you have a remote repository named origin from which your local repository can fetch all of its data from. Look in you .git/config file for details. The last step is simply to push the files you have in your local copy to the server.

[local]$ git push origin master

After running this, anyone on your team with an ssh account can clone the repository with:

[local]$ git clone ssh://publicsrv.example.com/srv/git/publicproject.git

If you’re lazy like me, and just want to be able to type git push/pull instead of typing out the public server’s name each time, add the following to your .git/config file:

[branch "master"]
        remote = origin
        merge = refs/heads/master

And with that, you’re done with the repository migration.

Step 4: Final Rails Tweaks

Your Git work is done.  These last items are final notes to make your new repository play nice with your Rails app.

Tell Capistrano about Git

The very last thing you have to do is tell Capistrano to pull your Rails app out of a Git repository during deployment rather than from Subversion.  This is quite simple.  In your deploy.rb file, add this line:

set :scm, :git

Also, be sure to set your repository URL to the new location.

Ignore logs and temporary files

You may need to create some of the directories depending on how your svn repository was set up.  Insert empty .gitignore files in them to ensure Git doesn’t ignore them.

[local]$ mkdir tmp
[local]$ mkdir log
[local]$ mkdir vendor
[local]$ touch tmp/.gitignore log/.gitignore vendor/.gitignore

Add the following to .gitignore in your root folder to ignore standard Rails files that you don’t want in your repository:

.DS_Store
log/*.log
tmp/**/*
config/database.yml
db/*.sqlite3

That’s it.  Your Rails app is now ready to modify and deploy from Git.

References:

Happy Birthday to Me

Tuesday, September 16th, 2008

I turned 30 today.  w00t!

Thanks to everyone who has played some part in my life and helped me to get this far.  My apologies to those of you who were banking on me meeting my demise before now.  Better luck in the next three decades.

Moved to WordPress

Monday, September 15th, 2008

So I finally got busy enough that it is no longer worth it to spend any time on writing the code behind my own blog.  Therefore WordPress is my new overlord.  All hail WordPress.

WordPress should allow me to spend more time writing and less time hacking.  Who knows, maybe I’ll even retroactively port all of those posts I’ve got reaching back to 2001.  (Don’t hold your breath.)  Anyway, more to come.