Show local commits with Git-Svn

On my current project we are using git-svn as the version control system. If you haven’t heard of git-svn, it’s a bi-directional ‘bridge’ that enables native Git repositories to interact with a Subversion respository. Basically your local repository will look and act like a normal Git repository (except for a few differences) and simply push to a remote Subversion repository.

One of the areas where git-svn differs to normal Git is when you have local commits which haven’t been pushed to the remote repository. So if I have made a local commit on a Git repository and I run git status I will get the following output:

# On branch master
# Your branch is ahead of 'origin/master' by 1 commit.
#
nothing to commit (working directory clean)

However, if I do the same with git-svn I will get the following output:

# On branch master
nothing to commit (working directory clean)

This has lead to some complications where somebody uses a workstation, assumes it is empty, and then accidentally pushes a local commit. The way to check if a commit is local is to look at the git log and see if a commit has an svn-id attached to it. To make things a bit easier, I decided to write a script that would check to see if I have any local commits and emulate the native Git behaviour.

To start off, I wrote the following bash script.

#!/bin/bash

git_commits=`git log -10 | grep ^commit | wl -l`
svn_commits=`git log -10 | grep git-svn-id | wc -l`
if [ "$git_commits" -gt "$svn_commits" ]; then
  difference=`expr $git_commits - $svn_commits`
  echo "# Your branch is ahead of 'origin/master' by $difference commit(s)"
fi

git status

Basically the script is looking at the last 10 commits and checking to see how many of them have an svn-id attached. If there are any without an svn-id I write this to the console. I then execute the normal git status command to emulate the native git behaviour.

Now if I run this script I will get the following output (assuming a single local commit).

# Your branch is ahead of 'origin/master' by 1 commit(s).
# On branch master
nothing to commit (working directory clean)

Pretty cool. Now I would like to be able to run this as a regular Git command. Git allows us to create our own extensions pretty easily – you simply need to name your script git-your_script_name (no extension), put it somewhere on your path (I went for /usr/local/bin) and then you can execute this script using Git. In my case I named my script git-svn_status which means I can now execute by running git svn_status.

I usually alias git status as git st so now I simply needed to update my .gitconfig to point to this newly created command.

[alias]
  st = svn_status

Now running git st will tell me when I have local commits, just like in native Git. Pretty cool! Happy coding.