How to use get Git, Things and Dropbox to work together

I've started using Things as a way to keep track of Things I've committed to doing, or should be doing, and I'm a big fan: it syncs nicely with an iPhone, and it's full of loads of lovely UI touches, like automatically loading the url, or email message URI you're looking at into the notes section when making a new to do item, or providing well thought out keyboard short cuts, or simply having a "Today" mode designed let you set targets just for today, and forgot about the rest of your ever growing todo pile.

There's one shortcoming I've found though, and that's using Things with more than one computer - it isn't supported by out of the box, and using Dropbox, my normal way of sharing content between two computers, doesn't play too nicely with Things by default either.

However, on Cultured Code's own wiki there there some handy instructions for using Git to allow multiple instances of Things to share a single tasks database, but setting up a remote git server just to share todo's across computers seems like a git of an overkill - instead, I've adopted them to work with Dropbox, using a simple directory to share repos, instead of using a whole separate server.

In this post, I'll outline, how to set this up for yourself.

What we're going to do here

This is a fairly lengthy post, so I'll outline what we're doing first:

a) setup an a Git Repo in Dropbox that we push updates to.

b) Set up a clone of this repo on computer where the Things todo database is normally stored, and track changes in there.

c) Setup something like a cronjob using OS X's equivalent, launchctl to commit the changes every half hour, and push them to the main Git repo on dropbox.

Of we go then...

Setting up our Dropbox Git Repo

First of all, we setup our repository in Dropbox like so:

  mkdir -p ~/Dropbox/Git-Repos/Things.git   

It should look something like this in the finder:

Now we have a directory for our git repo, we need to initialise it, using a special flag, --bare. This creates a repo that's ready for us to push code to:

  cd Things.git
  git --bare init

Congrats, that's step one done!

Cloning the repo into we we put our Things

Now we have somewhere to push code to, lets start pushing code. We're going to into the directory where Things data is stored, initialise a repo, and make our first commit:

  cd Library/Application\ Support/Cultured\ Code/Things
  git init
  git add .
  git commit -a -m "initial commit"

Okay, we've made our repo for Things, but we still don't have a way of getting content to the Dropbox repo, which is our canonical repo that we'd like to push code to. We need to tell git where the remote to push code to.

Normally with git, you'll push code to another server, but you can just as easily just push to another directory using git - this lets Dropbox handle the hard work of giving us distributed backups, and making this repo available to other computers:

  git remote add dropbox ~/Dropbox/Git-Repos/Things.git
  git push dropbox master 

Okay, so we've now created a central repo, we've created a local repo where we store our Things, and we've pushed our first chunk of code there too. Now we just need to automate this process, so we don't have to think about it in future.

Making this run on autopilot

For this, we turn to Launchd, a tool on the mac to run commands automatically in the background, somewhat like a a newer version of cron. It's what starts all your programs on boot, but it's also used to run certain tasks at certain times of the day on a schedule.

What we're going to do here is use it to run a shell script every 30 minutes when the computer is awake, to commit the latest state of the file storing our Things data locally, then push that changeset to the main repo on Dropbox. Paste this code into a file called

  cd ~/Library/Application\ Support/Cultured\ Code/Things
  git pull $REMOTE master
  git commit -a -m "Auto Sync - $DATE"
  git push $REMOTE master

The git pull line is there to keep this in sync with other instances of Things. The git commit line will aways give us a unique commit message, and the git push, makes sure we are pushing to the right branch.

Next, we need to breathe life into this script, by making it executable. We use a sometimes arcane unix command here, chmod (our +x part of the command gives it an executable bit, allowing it to be run by itself):

  chmod +x   

We need to put this newly enlivened script into a place where our launchctl daemons can actually access it, so let's put it into the user directory usr/local/bin - I tend to prefer this as a place for storing executable binaries than /usr/bin, because a) it means we don't have to start using sudo to make future changes, and b) it should be clearer that this isn't a core binary that would be clobbered by a software update from Apple.

  cp /usr/local/bin/ 

The final steps are creating a launchctl config file known as a property list, and putting it where the launchctl daemons normally look for config files, and then loading it in to launchctl to start running our cronjobs:

First paste this code into the property list file (more commonly referred to as a plist file) called com.$(hostname).ThingsSync.plist:



Then put it into the directory set aside for loading plist files, ~/Library/LaunchAgents:

  mkdir -p ~/Library/LaunchAgents
  cp com.$(hostname).ThingsSync.plist ~/LaunchAgents

Our last step before we're finished, is to load the plist file in launchctl, so it knows of its existence, without use needing to reboot the machine:

  launchctl load ~/Library/LaunchAgents/com.$(hostname).ThingsSync.plist 

Once this is done, we should now have our Things data being committed and pushed using git, every 30 mins while the computer is awake. If we want another machine set up work with this, we can clone from the repo in dropbox, follow steps 2 and 3, and at last, have multi-mac sync using Things.

Copyright © 2020 Chris Adams
Powered by Cryogen
Theme by KingMob