Monday, July 25, 2011

Working with Git - Part 1 - Our initial experience

When Adku first opened shop, we used Subversion for source control. Since then, we’ve migrated over to the wonderful world of Git and wanted to share why we moved and some aha moments we’ve experienced along the way.

Why we moved to Git
  1. Speedy commits and updates, subversion commits got to be painfully slow - sometimes taking minutes
  2. Cheap local branching
  3. Better merging. e.g. merges follow renames and code moves
  4. Better support for file renames and file permission changes
  5. Interactive commits or the ability to commit partial files

Our aha moments
  1. A “commit” is essentially a diff with a pointer pointing to the commit we created a diff from
  2. A “branch” is a pointer that can be updated to point to any commit
  3. Deleting a “branch” is akin to deleting the pointer to that commit, if you have another “branch” (pointer) pointing to that commit, your changeset will NOT disappear
  4. A “remote” is a reference to a clone of this repository. This clone is usually hosted on another machine but it can also be another repository on your own hard drive.
  5. “git pull” is effectively the same thing as a “git fetch && git merge”
  6. “git fetch” is safe to re-run and does NOT update any files in your branch. It updates your knowledge of where the “remote” repository thinks it is.
  7. “git rebase origin/master” works by uncommiting all your commits in reverse order, updating your branch to origin/master, then replays your commits in order
  8. Your repository will continue to think a branch exists on a “remote” repository even if it was deleted by another developer. To remove branches that don’t actually exist on the “remote” anymore, you can run “git fetch --prune”

At the end of the day, we realized that these insights did not come cheaply. We invested a lot of time trying to understand Git and we recognized that we could not afford to have every new hire spending weeks getting up to speed on a version control system.

We ultimately decided to write bash scripts for the most common developer actions to help encapsulate all our Git knowledge and best practices. The culmination of that project is a development model we’re calling Dr. Git (Develop/Release with Git) which we’re excited to share in a following blog post.

Tuesday, July 19, 2011

Redmine

There are so many issue tracking tools available today with so many features, it was hard to figure out which one was best for us.  We looked at JIRA, Trac, FogBugz, Plan.io and a few others, but in the end, we ended up choosing Redmine and hosting it ourselves.  

For our specific usage patterns, we had some very specific features that we wanted in an issue tracker.  Things like road map planning tools, searching, and UI were pretty pervasive, but there were a couple that we had trouble finding out of the box.
  • Tight email integration
    • We wanted to be able to reply-all to an email and add the issue tracker to create a new issue with the thread in the description.
      • Subsequent emails to the same gmail thread would then be automatically added to the issue.
    • We wanted to be able to modify issues directly from email using special syntax like "assignee: jesse" or "status: in progress".
  • Github integration
    • We wanted to be able to attach git commits to issues using special syntax in the commit message like "closes #12".
    • We didn't want to migrate our repository off of Github.

A lot of issue trackers do have email integration, but with one slight quirk.  If you reply-all and add the issue tracker, it creates a new issue.  If someone else then replies to the thread, a brand new issue gets created!  We wanted the issue tracker to be intelligent enough to realize that it was the same issue and update it instead of creating a new one.  Redmine didn't do this out of the box, but because it's open source, we edited a few lines and got it to work the way we wanted in a little less than 5 minutes.  This may seem like a small, subtle issue, but it's one that we now make use of many times each day so the impact is significant in our daily usage pattern.

A lot of issue trackers integrate well with source control, but they require you to host your repository with the issue tracker!  This means that we'd either have to move our repo off of Github or we'd have to setup processes to push our code to two repositories.  Pushing to two repositories sounded like a potential nightmare and few issue trackers allow you to integrate with an external repository like Github.  What we ended up doing was syncing our Redmine repository directly from Github using a cronjob.  Post-commit hooks would have been better, but we left that as a TODO since it would require more than 5 minutes to setup and the cronjob was sufficient for the job.

Redmine's got some great plugins too.  We use the backlogs plugins for a great drag-n-drop UI and burndown charts. 

Given that we've already made two edits to the issue tracker, we felt great peace of mind choosing an issue tracker that was open source and self-hosted so we can modify it to suit our needs whatever they may be.  Oh and also, it's free =).