Jan 29 2010

A successful Git branching model

http://nvie.com/archives/323

Detailed overview and explanation how to use Git branches to manage a project.


Jan 07 2010

Two tricks to improve your Thunderbird experience

I receive lots of emails from mailing lists and use a filter script on the server to sort the emails into different folders. I also use the keyboard rather than the mouse to skip from one unread email to another (press n). However when crossing folders, an annoying popup asking Advance to next unread message in [folder]? appears. To disable it and make Thunderbird automatically advance to the next message set mailnews.nav_crosses_folders to zero.

To keep my inbox empty I immediately archive all messages from my inbox which I've read and processed (Inbox Zero policy). Thunderbird makes it very easy and provides a keybinding for this action (press a). By default it puts the message into per-year subfolders inside Archives/. But with the excellent search features in Thunderbird it makes little sense to organize the messages in such way. Thankfully, the granularity can be controlled with a pref key. Set mail.server.default.archive_granularity to one of the following values to control how Thunderbird archives the messages:

const long singleArchiveFolder = 0;    /* .../                */
const long perYearArchiveFolders = 1;  /* .../[year]/         */
const long perMonthArchiveFolders = 2; /* .../[year]/[month]/ */

To edit the pref keys, open the Thundrebird preferences window, go to the Advanced section and in the General tab you'll see a button Config Editor. After confirming that you understand the risks, the editor will pop up. You can use the filter on top to search for the two keys and then set them to your preferred values.


Jan 06 2010

Forward-porting patches using Git

Then source code of MacFUSE, the FUSE port for MacOSX is quite a mess. For one, the SVN repository contains a tarball with the FUSE userspace libary which was originally written for Linux and a patch which is applied to the extracted files to make the source compile on MacOSX. The tarball seems to contain fuse version 2.7.3 which is almost two years old now. And because the patch is against the tarball and not the source, most of it are changes to autoconf/automake generated files. That makes it hard to see what the actual changes are. Today I have tried to forward-port the patch to the latest version.

The basic idea was to first get the patch into git, and then use cherry-pick to forward-port it. Obviously the patch would apply cleanly to the extracted tarball, so first thing I did was to create a new Git repository, extract the tarball into it and apply the patch in a separate commit:

tar -xvzf ../macfuse/core/10.5/libfuse/fuse-current.tar.gz
mv fuse-2.7.3/* . && rmdir fuse-2.7.3
git add . && git commit -m 'Import fuse-current.tar.gz'

git apply < ../macfuse/core/10.5/libfuse/fuse-current-macosx.patch
git add . && git commit -m 'Apply the macfuse patch'

Now that the patch is recorded in the Git repository as a commit, I can use cherry-pick to apply it to latest version. FUSE still uses CVS but thanks to git cvsimport it was no problem to import the source into Git. I checked out the latest version and cherry-picked the patch:

git checkout upstream-cvs-source
git cherry-pick master

As expected, cherry-pick failed because the patch didn't apply cleanly as there have been many changes since 2.7.3 and the latest version. After I had fixed some of the issues and tried to compile the code, it failed because upstream has removed a field (tree_lock) from a structure that the cherry-picked code was using. Using git log -Stree_lock I was quickly able to find out in which commit the field was removed and using git show I saw what exactly the developers had changed. And that all did not take more than ten seconds! After a fixing the remaining issues, the code compiled cleanly.

The lesson learned? Just get your source somehow into Git. Once your code is there, you'll find it so much easier to navigate it. Who introduced a certain string? Easy, use git log -S<string>. Who wrote this line? git annotate <file>. All these commands take only a fraction of a second to get you the result that you need. And this is where you'll learn to appreciate the power of Git.


Jan 05 2010

How to amend the root commit

This morning I imported ccache into a Git repository (available now on github). I often do that with software for which there is no existing Git repository. The source of ccache is only available in tarballs, but that's not a big deal because Git comes with a script to import a set of tarballs (contrib/fast-import/import-tars.perl). However, the script generates rather ugly commit messages. Editing commit messages, even of commits which are far back in the history, is not a problem for Git, but editing the root commit can be tricky. This is what I used:

# find the root commit sha1 and check it out
# (this detaches HEAD but don't worry about it)
git checkout <root commit>

# amend/edit the commit as you want
git commit --amend

# go back to the branch you were before
git checkout -

# now rebase all the remaining commits on top of this new root
git rebase --onto HEAD@{1} <root commit>

You could even use interactive rebase in the very last command if you wanted to edit the remaining messages. Or you can use git rebase -i <new root commit> at any point later.


Jan 01 2010

Ubuntu dual-booting as host and guest

The primary OS on my ThinkPad laptop is Gentoo. I've intentionally chosen the amd64/no-multilib profile, meaning that portage compiles and installs only 64bit libraries and applications. That also means that I can't run any 32bit applications such as most closed-source apps that are available only in binary form (Skype comes to mind) or Windows games which run under Wine. Even though I do fine without, sometimes I do want to run those apps. But at the same time I want to keep my system clean of 32bit cruft. For me the solution has been to install 32bit Ubuntu in a virtual machine. However running software in a VM comes with a performance penalty. And in case of games that is just plain unacceptable.

Dual booting would give better performance, but when I just need to quickly run a 32bit app I don't really want to reboot the computer. So I settled for a hybrid solution: Install 32bit Ubuntu so that I can boot it as host or as guest inside the Gentoo host. The basic approach is described in a section of the ArchWiki page about QEMU: Using any real partition as the single primary partition of a hard disk image. I only had to adjust the size of the mbr file, 16 Kilobytes was too small. I created a four Megabytes file (dd [...] count=8192) and set 256 heads, 32 sectors in fdisk so that the first partition can start at cylinder 2. After building the md array, I started kvm and installed Ubuntu. One thing I paid attention to is to manually set up the partitions, to prevent the automatic partitioning tool from moving the beginning of the first partition.

To make the system bootable directly from the BIOS I had to copy the Ubuntu kernel and initrd from the Ubuntu partition into my Gentoo host and then update lilo appropriately. Be sure to first stop the md array (mdadm --stop /dev/md0) before you mount the partition! The entry in my /etc/lilo.conf looks as follows:

image = /boot/vmlinuz-2.6.32-9-generic
    label = ubuntu
    initrd = /boot/initrd.img-2.6.32-9-generic
    read-only
    root = /dev/sda8

Then I only had to run lilo to update the boot manager and voila, now I have a new entry in my lilo prompt: ubuntu. Selecting that boots the 32bit Ubuntu system. And whenever I'm on my Gentoo host and quickly need access to the Ubuntu system, I simply build the md array and boot it with kvm.

In case you are wondering why I have eight partitions (the Ubuntu system installed in /dev/sda8): I have partitions for swap, root, home, pool (large files, games etc), priv (was supposed to become an encrypted partition, but I don't use it for anything right now) and then three 20GB partitions for virtual machines. I created the three partitions so that the VMs can access the harddrive directly and avoid the overhead of the filesystem. Also, because MSDOS partition table can only access more than four partitions with quirks (extended partition), I decided to use GPT which supports up to 128 partitions. Unfortunately GRUB doesn't support GPT yet (version 2 does, but that is still under development) so I had to settle for lilo. But I don't mind because I don't need the additional features that GRUB provides anyway.