I’m not an idiot… I promise!

I hate new jobs. I like getting to work on new projects, I like learning new things and I like meeting new people, but I hate the actual “new job” stuff. I don’t like looking for jobs, I don’t like interviewing, I don’t like being the new guy who doesn’t know anything. Due to circumstances related to the recent economic turmoil, I decided that regardless of my aversion, it would be a good idea to start searching for new employment.

I started looking and, on one of my first phone interviews, was asked, “What is an interface?”

I know what an interface is. I’ve written new interfaces; I can create a class that implements IComparable, IDisposable and IMakeMillionsFromCrazyIdeas without breaking a sweat. I can talk at length about why multiple-inheritance is pure evil and how single-inheritance, combined with interfaces, will solve every problem known to man. If you would prefer, I can argue the inverse. But, when asked, “What is an interface?” I babble like an idiot:

Oh, an interface is a thing that classes have and they start with an ‘I’ in C# anyway but it’s by convention not a requirement and they come after the class name and a colon and they help us to do things so that when other classes want to do something they know that our class can be used to do that thing because our class implements the interface.

I’s a rel gud programur. I got teh 1337 h@X0r skillz. yeah…

I knew the answer, but on the spot, I couldn’t figure out how to intelligently convey that knowledge. I hadn’t been asked to verbalize that knowledge for a long time. Since I don’t like feeling like an idiot, I spent some time googling “interview questions.” I don’t remember which site recommended the book, but I ended up buying Programming Interviews Exposed: Secrets to Landing Your Next Job, 2nd Edition.

Programming Interviews Exposed was a good purchase. If you you’re not already familiar with some basic concepts of computer science I doubt this book would be very useful. But for me it was a great refresher on concepts I use regularly, but hadn’t consciously thought about for a while. Who thinks about the nuts and bolts of programming when you’re in the zone, and it’s just flowing?

As you would expect from a job hunting book, there are chapters on the basics of job hunting: how to decide what companies you want to work for, how to find job opportunities, how to work with headhunters, how to negotiate offers, etc. I wouldn’t necessarily consider myself an interview-pro but, many of these tips just seemed like common sense.

The book describes methods for solving riddles and how to answer questions. It doesn’t just provide a bunch answers to memorize but discusses ways to convey your knowledge and experience to the interviewer (hint: keep talking and explain what you are thinking). The chapters that I found most useful were the computer science topics: linked lists, trees and graphs, arrays and strings, concurrency, etc. The book gives questions that might be presented in an interview then explains the answers.

To date, I haven’t been asked any of the questions presented in Programming Interviews Exposed. Reading examples of various ways to traverse trees and reverse strings was useful. The interviewer does not want return new string (Array.Reverse ("xyzzy".ToCharArray()));. It was useful enough that, when asked to calculate the weight of tree nodes and return a specific node in O(n) time, I felt confident in my answer.

Programming Interviews Exposed will most likely benefit those who are already familiar with basic computer science concepts. It’s a quick read and quite effective. Good luck with your next interview!

Managing WordPress Updates with Git

WordPress 2.7 was recently released so I started the process of updating the handful of WP instillations that I manage. Git has made this process a breeze! Here’s how I do it.

  • To start a new project, use subversion to download the latest stable release of WordPress
  • Add that entire directory, including the .svn folders, to git. To keep subversion happy, make sure that all of the svn tmp directories are in git (use an empty .gitignore file to force git to add empty directories)
  • Before you make any changes, create a new branch in git called wordpress_base. You should never do anything with this branch other than update the WordPress code from subversion.
  • Switch back to master and change whatever needs changing (e.g. add themes, plugins, etc.). To make upgrades go as smoothly as possible you shouldn’t modify the base WordPress files more than you absolutely have to but, adding themes and plugins should be no problem.
  • When everything is tested and ready to deploy, commit everything to git and push to the webserver

The command line will look something like this:

$ cd ~/Downloads
$ svn co http://svn.automattic.com/wordpress/branches/2.6/ new_blog
$ cd new_blog
$ git init
$ git add .
$ git commit -m "Import WordPress 2.6"
$ git branch wordpress_base
## Get the site completely setup, commit everything to git and
## push everything up to the server.

When you’re ready to update WordPress:

  • Checkout the wordpress_base branch
  • Either ‘svn up’ or ‘svn switch’ to get the newest code
  • Check all of the changes in to git
  • Merge wordpress_base back in to master (I generally rebase then merge)
  • After everything in git has been committed, push, pull or do whatever fits your process to get the updated code from your development machine to the server
  • Don’t forget to upgrade your blog database after the new code has been deployed by going to: http://myblog.com/wp-admin/upgrade.php
$ git checkout wordpress_base
$ svn switch http://svn.automattic.com/wordpress/branches/2.7
$ git add . && git ls-files --deleted | xargs git rm
$ git commit -m "Updated WordPress to version 2.7"
$ git checkout -b integration
$ git rebase master
$ git checkout master
$ git merge integration
$ git branch -d integration
## Make sure all conflicts have been resolved, test the new site and
## update plugins. Commit changes to git and push them to the server.

Migrating from svn to git

About a year ago I decided that it was time to try git. As a long-time user of SVN, CVS and even VSS *shudder*, I wanted to see what all the fuss was about. At first I didn’t get it; having never used a DVCS before I just didn’t grok the concept but I keep with it and one day it clicked. After a few weeks I was completely hooked and have since migrated most of my personal repositories from SVN (I haven’t tried it under Windows so I haven’t migrated my VisualStudio projects yet).

Not long after my conversion, we decided to start using git for a few projects at work. Since then we’ve been using both subversion and git on a self-hosted server. As anyone who gets git can tell you, after using a DVCS subversion can feel very limiting so we recently decided to migrate everything from subversion to git. We decided to host all of our repositories on github.

This is a long way to say that, over the past year I’ve migrated ~20 subversion repositories, of varying complexity, over to git. The process is not terribly difficult but there are multiple steps that you have to remember. I’ve kept a list of each step and thought that it might be useful to someone else (or perhaps myself when I need to do this again in a few months 😉 ).

To migrate the subversion repository my_great_app to git first you’ll create an empty git repository. Note that this just does the setup, no import happens at this point.

$ git svn init -s svn://svn.zobie.com/svn/my_great_app my_great_app
$ cd my_great_app

Now, if you want your new git history to look pretty, you need to create a text file that maps subversion users to git users. For this example I’ll name the file ~/users.text; it should look something like this (svn user on the left, git user on the right):

(no author) = Unknown Author <unknown@zobie.com>
nate = Nate Zobrist <zobie@zobie.com>

Then you tell git about your authors file and start the import:

$ git config svn.authorsfile ~/users.text
$ git svn fetch

Honestly, I don’t really understand the “fetch-all” option but on one of the larger repositories that I migrated, the initial import didn’t seem to be complete. I started completely over and when I ran “git svn fetch” I included the “–fetch-all” option. This significantly increased the amount of time that the import took but it seemed to do the trick.

$ git svn fetch --fetch-all

At this point your entire subversion repository has been imported into git and we want to create a tag in git that corresponds to each of the tags in subversion:

$ git branch -r | sed -rne 's, *tags/([^@]+)$,\1,p' | while read tag; do echo "git tag $tag 'tags/${tag}^'; git branch -r -d tags/$tag"; done | sh

Then, for each svn branch, we create a branch in git:

$ git branch -r | grep -v tags | sed -rne 's, *([^@]+)$,\1,p' | while read branch; do echo "git branch $branch $branch"; done | sh

These two commands will import every tag and branch from subversion. Sometimes git finds branches that you didn’t know existed. Just delete whatever branches and tags that you don’t want persisted.

Now that the repository is setup like we want, we do some housework to shrink and compact the repository.

$ git repack -d -f -a --depth=50 --window=100

Then we remove the meta-data that was used by git-svn:

$ git config --remove-section svn-remote.svn
$ git config --remove-section svn
$ rm -r .git/svn

At this point you have successfully migrated your subversion repository into git! If you aren’t going to push this repository to a centrally hosted server you can stop at this point and enjoy using your new git repository.

If you want to keep a copy of your repository on a self-hosted server then create a bare clone and copy it up. Then configure your new server as “origin.” You’ll be happiest if you make sure that the master branch is checked out before cloning the repository.

$ git checkout master
$ cd ..
$ git clone --bare my_great_app my_great_app.git
$ scp -r my_great_app.git zobie@git.zobie.com:/git/.
$ rm -rf my_great_app.git
$ cd my_great_app
$ git remote add origin ssh://git.zobie.com/git/my_great_app.git

Alternatively, if you want to push the repository to github, use the the clone url that they provide:

$ git remote add origin git@github.com:zobie/my_great_app.git
$ git push --all && git push --tags

The last thing that you need to do is to point your “master” branch to “origin/master”. There is probably a way to do this from the command line but I don’t know it. I can’t give exact instructions for modifying the config but the process isn’t difficult. Open .git/config and point your master branch to origin; it should look something like this:

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

If you have other local branches that should track their remote counterpart, you will need to make a similar change for each.

You can test that everything is working:

$ git pull
$ git push

Assuming you don’t get any errors, you’re done!

Update 2009-01-13: Corrected an error in the sed regex. The ‘1’ should be escaped.