Using Git and Dropbox with a Bitcasa Upstream

After using GitHub to contribute to a project the other day, I got to thinking about other uses for Git. One was to keep a backup of my ~/bin folder. I write a lot of one-off scripts to make my life easier. Most of the time they’re under 20 lines and previous versions aren’t really needed. But sometimes1 I break things. Other times I’ll go back and wonder what the hell was I thinking.

I already use Dropbox, so why not put a repository there? I just prefer to have the files separate. There’s some talk about how the Dropbox backup version will conflict with the Git files. I’ll only be using it for a bare repository not a working directory. So Dropbox can do it’s thing and it won’t cause me problems.

Since I also use Bitcasa Drive, it seems natural to make that into my upstream repository. Bitcasa is different from Dropbox in that the files stored there are not on your local hard drive. They’re on the Bitcasa drive which is mounted as a network share. So it is true off-site backup. Access to it also depends on having an Internet connection. It’s a place for backups not daily work.

Once set up, I’ll be able to commit changes to either or both remote repositories. If I’m working offline I can push commits to Dropbox and have them synced up later. The reason to add Bitcasa is to have another backup and Git makes this easy.

Most of the guides I found were for creating a new project. I already had a folder of scripts, so the steps are little different. The basic set up is the same. Initialize the repository, then add the files and make the first commit. Now this folder is version controlled.

$ cd ~/bin
$ git init
Initialized empty Git repository in ~/bin/.git/
$ git add *
$ git commit -m "Start tracking ~/bin"
\[master (root-commit) 393f7fd] Start tracking ~/bin
 60 files changed, 1064 insertions(+)
...

To make it work with Dropbox we have to clone it into wherever Dropbox keeps it’s files. On my laptop, that’s ~/Dropbox.

$ git clone --bare --no-hardlinks . ~/Dropbox/git/bin-git
Cloning into bare repository ‘~/Dropbox/git/bin-git'...
done.

Do the same for Bitcasa.

$ git clone --bare --no-hardlinks . /Volumes/Bitcasa\ Drive/git/bin-git
Cloning into bare repository '/Volumes/Bitcasa Drive/git/bin-git'...
done.

Notes:

  • Git will create any folders needed, so there’s no need to create ~/Dropbox/git first.
  • I changed the name to bin-git so I’ll remameber exactly what it is when looking at file names.
  • The option --no-hardlinks makes sure the files are physically copied. This might be the reason some people have problems with Dropbox.2
  • Don’t forget the dot! . means use the current folder.

Now we have our remote repositories but they aren’t usable just yet. We can link them with the remote add command.

$ git remote add origin ~/Dropbox/git/bin-git
$ git remote add upstream /Volumes/Bitcasa\ Drive/git/bin-git

Workflow

I wanted a simple way to remember what I had set up. My ~/bin scripts aren’t something I work on everyday. So the less remembering I have to do, the better.

First track Bitcasa as the default.

$ git push --set-upstream upstream 
Branch master set up to track remote branch master from upstream.
Everything up-to-date

The way I set up a working folder was to create a new branch for Dropbox called amazingly enough dropbox.

$ git co -b dropbox
Switched to a new branch 'dropbox'

This will be the branch that I’ll use for most of my work. I can also set it to push to Dropbox as the default.

$ git push --set-upstream origin dropbox
Total 0 (delta 0), reused 0 (delta 0)
To ~/Dropbox/git/bin-git
 * [new branch]      dropbox -> dropbox
Branch dropbox set up to track remote branch dropbox from origin.

Now while in this branch, git push will do what I expect. It will push the dropbox branch to the Dropbox repository.

The way I’ll uses these are:

  • dropbox branch: local saves of my commits, where most of my work happens.
  • origin/dropbox branch: local changes are pushed here to be saved on Dropbox.
  • master branch: I’ll merge dropbox into this when I add new files or have major changes.
  • origin/master branch: the local master branch saved on Dropbox.
  • upstream/master branch: the local master branch saved on Bitcasa.

Example

In this case I’ve made changes to file named target.rb in the dropbox branch. Here’s how I’d sync everything up.

Switch to the main branch:

$ git checkout master 
Switched to branch 'master'
Your branch is up-to-date with 'upstream/master'.

Bring my working changes up to the branch master:

$ git merge dropbox master 
Updating 1d3f955..44d996e
Fast-forward
 target.rb | 1 +
 1 file changed, 1 insertion(+)

Save to Bitcasa:

$ git push upstream master 
...
To /Volumes/Bitcasa Drive/git/test/
   1d3f955..44d996e  master -> master

Save to Dropbox:

$ git push origin master 
Total 0 (delta 0), reused 0 (delta 0)
To /Users/jenn/Dropbox/git/test/
   1d3f955..44d996e  master -> master

Switch back to the working branch:

$ git checkout dropbox
Switched to branch 'dropbox'
Your branch is up-to-date with 'origin/dropbox'.

The usual update for saving working changes to Dropbox:

$ git push
Everything up-to-date

Conclusion

With the various backup services available and the number of ways to use Git, the permutations of someone’s “perfect” system are endless. This is the way I like to work. It mirrors a GitHub project workflow. Once I started thinking that way, it became easier to make everything work like that.

There are also a few hidden benefits.

The Dropbox repository folder can be shared with other people. Giving other team members write access to the folder is a quick way to share code. But since the Dropbox server doesn’t speak Git, there’s a chance of files being overwritten. If this were to happen the clean copy on Bitcasa could be used to restore the project.

It can also be shared via a URL, and be downloaded as a zip file from the Dropbox site. This way teammates can quickly grab the files with the commit history intact.

“It’s like living in the future, man!”


  1. More often than not. That’s learning for ya’!
  2. This might be the source of people’s problem with Git and Dropbox. The default behavior for Git is to create hard links on the local drive. This would mean the Dropbox files are updated as frequently as the working files. It’s better to have independent copies and have it work like a remote repository.