git-svn and ReviewBoard

The cat in the tree is looking at me
This cat is ON MY BRANCH! Image by pinto_2003

The company I am currently at haven’t yet made the jump to git. It’s understandable; there are a number of large SVN repositories and only one (or two) of the developers know how to use git. So, it doesn’t make sense right now. I’m trying to get git-svn working accurately in my workflow before I try and explain the awesome-ness of git for my colleagues. I’ve run into two problems, one is svn:properties and how git doesn’t support them (except ignore) which is a pain, because it means that if I want to adhere to AWin coding standards and not have PHPUnderControl moan at me, I need to have svn:keywords and svn:EOL properties for each file. The hacky fix is to run a seperate SVN directory on my box, which I add files to, add the properties, then rebase them into git. It’s a pain.

The other problem is ReviewBoard. Well, it’s not such a massive problem now ReviewBoard has ‘post-review’ which allows you to send reviews to RB via the command line. But, sometimes, you just want a standard diff file which you can upload to RB, git diff doesn’t create files that ReviewBoard understands, which is where a little bit of bash scripting comes into play.

I found this: My (work) Git Workflow (You should read it all, it goes into managing branches and stuff, it’s a useful read if you’re just starting out with git-svn, thanks Seth!). Which almost worked. Except, for some reason, it was pumping out massive diff files that git diff wasn’t. So, I had a little bit of a fiddle and found that it uses the git config option svn-remote. Which, for my repo is set to the trunk. Which doesn’t make any sense if I want to run an diff on the branch I’m working on, so, I modified it:

#!/bin/bash
#
# git-svn-diff originally by (http://mojodna.net/2009/02/24/my-work-git-workflow.html)
# modified by mike@mikepearce.net
#
# Generate an SVN-compatible diff against the tip of the tracking branch

# Get the tracking branch (if we're on a branch)
TRACKING_BRANCH=`git svn info | grep URL | sed -e 's/.*\/branches\///'`

# If the tracking branch has 'URL' at the beginning, then the sed wasn't successful and
# we'll fall back to the svn-remote config option
if [[ "$TRACKING_BRANCH" =~ URL.* ]]
then
        TRACKING_BRANCH=`git config --get svn-remote.svn.fetch | sed -e 's/.*:refs\/remotes\///'`
fi

# Get the highest revision number
REV=`git svn find-rev $(git rev-list --date-order --max-count=1 $TRACKING_BRANCH)`

# Then do the diff from the highest revition on the current branch
git diff --no-prefix $(git rev-list --date-order --max-count=1 $TRACKING_BRANCH) $* |
sed -e "s/^+++ .*/&     (working copy)/" -e "s/^--- .*/&        (revision $REV)/" \
-e "s/^diff --git [^[:space:]]*/Index:/" \
-e "s/^index.*/===================================================================/"

You can also see it here: http://gist.github.com/582239

So far, it seems to be working for me. But it’s only until I get the department using git right, RIGHT?

Advertisements

git status on multiple repos

Show_status
git status is now better

Often a lot of the work I do is on services. This means that, in any given day, I’ll perhaps be working on one or more repos. As is the way of git, I commit often to the local working branch and they push to the master at the end of the day, or whenever I’ve got feature, or patch of fix or whatever that needs to go back upstream. First thing in the morning, I’ll also do a pull for each repo I’m going to work on, including dependent repos.

If you’ve got a lot or repos, this quickly gets tedious to cd into each directory, run git status, then git push or git pull, cd back out, then into the next directory, etc etc.

So, I wrote a wee python script called ‘show_status’

Usage: show_status [options]

Show Status is awesome. If you tell it a directory to look in, it'll scan
through all the sub dirs looking for a .git directory. When it finds one it'll
look to see if there are any changes and let you know. It can also push and
pull to/from a remote location (like github.com) (but only if there are no
changes.) Contact mike@mikepearce.net for any support.

Options:
  -h, --help            show this help message and exit
  -d DIRNAME, --dir=DIRNAME
                        The directory to parse sub dirs from
  -v, --verbose         Show the full detail of git status
  -r REMOTE, --remote=REMOTE
                        Push to the master (remotename:branchname)
  -p PULL, --pull=PULL  Pull from the master (remotename:branchname)

Just running ‘show_status’ will always run a non-verbose check on any sub dirs in your current dir, so:

%> show_status
-- Starting git status...
Scanning sub directories of /home/sites/
--/home/sites/gitstatus        : No Changes
--/home/sites/projectone    : No Changes
--/home/sites/project2        : No Changes
Done

You can also pass in a directory that you want to use, this is useful if you wanted to use it in other scripts, or if you’re not in a root directory:

%> show_status -d/home/sites

You can add a pull request, which will pull from a remote master. It’s important to note that it’ll only pull from a remote master if there are no local changes waiting to be committed. This is to force you to manage your merges carefully.

%> show_status -pmikepearce:master

Finally, you can do push requests as well, again, this will only work on repos where there is nothing waiting to be commited:

%> show_status -rmikepearce:master

You can grab the whole thing on github (Git Status), or just clone/fork here: git@github.com:MikePearce/Git-Status.git

A little bit of git

Using git after SVN is like driving a Ferrari after driving a Jaguar. Nimble, speedy, lovely. My word it’s beautiful.

Anyway, I’m learning my way around it and, recently, came across these two lovely things:

Colouring the git output (from @catchamonkey)

I didn’t realise how useful colouring the output of things like git diff and git status etc was until I’d done it. Follow the below:

%> vi ~/.gitconfig

This will open the global .gitconfig file for your CURRENT user in vi. It will probably look something like this:

[user]
 name = Mike Pearce
 email = mike.pearce@jellyfish.co.uk

Below all that, you’ll need to add this:

[color]
        ui = auto
[color "branch"]
        current = yellow reverse
        local = yellow
        remote = green
[color "diff"]
        meta = yellow bold
        frag = magenta bold
        old = red bold
        new = green bold
[color "status"]
        added = yellow
        changed = green
        untracked = cyan

Obviously, you can change the colours to suit your particular pallete, but the above are pretty cool!

Global Ignorance (via @nefarioustim)

Sometimes, you’ll want to ignore the same file for each git repo. You can add the ignored files to the git repo itself, or, if you know there’ll always be a file or files you want to ignore, you can add it to git excludes.

I use netbeans on a mac, so I generally ignore the following:

  • .DS_Store
  • ./nbproject
  • *.pc (compiled python code)

You can do it by editing the .gitconfig file again:

%> vi ~/.gitconfig

Then adding the following lines somewhere:

[core]
 excludesfile = ~/.gitexcludes

OK, save then, then do this:

%> vi ~/.gitexcludes

and add each one on a new line:

DS_Store
nbproject
*.pc

Save that et voila. You’ll never be troubled with those files being added to your repo again.