Git in one minute

Based on notes from a recent BarCamp, here\’s my one-minute introduction to Git, a distributed revision control system (a system for managing collaborative changes to files, usually used for software development). This is probably only useful to someone who\’s already a programmer and already trying to use git, as a kind of cheat-sheet.

git notes


Step 1: Create a directory with files in it. Done? Good. Let\’s proceed. “cd” into the directory and…

$ git init <- initialise repo

$ git status <- tells you which files are / are-not in version control

$ git add … <- add files to repo, do it for each “meaningful change”

$ git commit <- commit new files to repo

$ git commit -am “Feature 1” <- commit all changed files to repo, -m “message” sets message without loading $EDITOR

$ git log <- shows recent changes

$ git config “” –global <- configure email notifications

$ git branch feature1 <- create a “branch” for feature1. You should branch for each feature

$ git branch <- list branches. “*” indicates current branch

$ git checkout feature1 <- switch to branch “feature1”

$ gitk –all <- horrific-looking but useful GUI

$ git merge feature1 <- merge changes on feature1 into current branch(example assumes you\'re on a different branch)

If you get a merge conflict, it will look like this:

Auto-merged file1
CONFLICT (content): Merge conflict in file1
Automatic merge failed; fix conflicts and then commit the result.

Hope this helps someone else as much as it helped me…

Synchonising Google contacts with your OS X Address Book without an iPhone

So, I lost my iPhone a while ago and that was annoying.

Then my annoyance doubled when I realised that my Google contacts were no longer being synced to my OS X Address Book. It turns out that Apple will only let you synchonise Google contacts when you have an iPhone connected to the system.

This would have to be the most brain-damaged mis-feature I\’ve seen in years. It\’s not like my laptop has to access Google through the iPhone. It\’s just a completely arbitrary co-dependence of two otherwise utterly unrelated features of the computer.

Luckily there\’s a workaround for those who no longer have an iPhone but enjoyed the Google Contact syncing. It\’s a short script, so only really useful to those willing to get their hands dirty in the shell.

echo "Syncing Contacts with Google"
/System/Library/PrivateFrameworks/GoogleContactSync.framework/Versions/A/Resources/gconsync --sync
echo "Sync Complete"

There – done! I suppose you could turn it into a launchd script if you\’re really keen, but I\’m happy to just run it by hand from time-to-time. Eat it, Apple!

Guest Appearance on Byte Into It

Last week on Melbourne\’s 3RRR, Georgia Webster, Andrew Fish, Keren Flavell and myself discussed Windows 7, TinyXP, iPhone security, defamation, video games, the seeming success of the Australian \’net filtering trial and my experiences at the Open Video Conference.

It was a really fun experience and reminded me how much I miss radio. There\’s something very liberating about such a simple live medium, and you don\’t have to worry about whether you\’ve got food on your shirt. Radio is kind of a nerd\’s dream, because it\’s closer to “pure thought” than all the live visual media.

You can download the MP3 here.

Brix Rules

Ok, so I\’ve been playing with Brix, a CMS toolkit from the creators of Apache Wicket that uses Apache Jackrabbit as its content repository.

And it rules.

Jackrabbit (a JCR implementation, i.e. a hierarchical repository for all sorts of content) is maturing fast, with 1.5.0 hot off the presses. It\’s performance is really quite good in my simple tests (most page loads creating just one highly optimised database hit).

Wicket is also about to take a great leap, thanks to 1.4\’s generics helping everyone keep their code type-safe.

Brix\’s own architecture is fascinating. It currently has a very simple GUI, but don\’t let that fool you – there\’s a lot of hidden power underneath, and the code is very clean and well-factored (if under-commented in parts…)

The combo is a winner, so I\’m actually switching the bulk of my own CMS over to Brix as of today. Lots of work, but I get the feeling it\’ll all be worthwhile.

Sending HTML Email with Wicket part II: Converting links

In my previous post, I showed how you can use Wicket\’s HTML rendering engine to render HTML emails by faking a request/response cycle.

In this post, I\’ll show you how to use an IVisitor to change image and anchor URLs to be absolute instead of relative. This is absolutely essential in order to make your HTML email work – otherwise all your images can\’t be found, and your links point to your own mail server.

The trick is to use Wicket\’s IVisitor to add a TransformerBehaviour to all the Images and Links that uses a regex to transform the URL after render but before the page is returned.

The code for the IVisitor is below:

private final class RelativeToAbsoluteUrlVisitor implements IVisitor {
        private final String requestPath;
        private Pattern urlPattern;
        private Class<? extends Component> componentClass;

        private RelativeToAbsoluteUrlVisitor(String requestPath, Class<? extends Component> componentClass, String attributeName) {
            this.requestPath = requestPath;
            this.componentClass = componentClass;
            urlPattern = Pattern.compile(attributeName+"="(.*?)"");

        public Object component(Component component) {
            //if this component is of the specified class, update the URL attribute to be absolute instead of relative
            if(componentClass.isInstance(component)) {
                component.add(new AbstractTransformerBehavior() {

                    public CharSequence transform(Component component,
                            CharSequence output) throws Exception {
                        log.warn("Transforming component output: "+output);

                        Matcher m = urlPattern.matcher(output);

                            String attributeValue =;
                            int start = m.start(1);
                            int end = m.end(1);

                            //convert relative to absolute URL
                            String absolutePath = RequestUtils.toAbsolutePath(requestPath, attributeValue);

                            log.warn("Got absolute path \'"+absolutePath+"\' from relative path \'"+attributeValue+"\'");

                            //construct a new string with the absolute URL
                            String strOutput = String.valueOf(output);
                            String finalOutput = strOutput.substring(0, start)+absolutePath+strOutput.substring(end);

                            log.warn("Returning updated component: \'"+finalOutput+"\'");

                            return finalOutput;

                        return output;
            return IVisitor.CONTINUE_TRAVERSAL;

Then we override the onBeforeRender() routine to traverse the component hierarchy and add this behaviour to the appropriate elements. Note that I haven\’t shown how you get the current absolute request URL, as in my system this is proprietary. There\’s plenty of example code floating around on how to do that, anyway.

    protected void onBeforeRender() {

        final String requestPath = MyCustomWebRequestCycle.get().getCurrentUrlAsString();

        IVisitor imageVisitor = new RelativeToAbsoluteUrlVisitor(requestPath, Image.class, "src");
        IVisitor anchorVisitor = new RelativeToAbsoluteUrlVisitor(requestPath, Link.class, "href");

        visitChildren(Image.class, imageVisitor);
        visitChildren(Link.class, anchorVisitor);

So there you have it! All the bits and pieces to create HTML email with Wicket. There\’s one more catch though: You have to generate these emails in the same process as the Wicket Application. Calling Application.get() outside of the main process results in an error. In my system, I get around this by generating the HTML email source every time the user saves my Newsletter bean, which means that when it\’s finally sent (in the background), it just sends the pre-generated HTML. Easy!