For the past two days, I’ve been giving git-svn a go at work. I was wanting a way to easily create task branches without touching the central subversion repository, and someone I worked with tipped me off to git’s standard svn interaction (thanks Eric). Plus I was just curious to learn more about git.
Here are my experiences and impressions so far.
My Setup
At work, I’m using IntelliJ Idea 8.0.1 on a Windows XP machine. The code I’m working on right now is a module contained within a larger framework, so I’m actually dealing with two subversion repositories; one for the framework, and another for the module. The larger project points to the module via an svn:externals definition.
Installing git With Cygwin
The first thing I did was get an install of git going. Since I’m using XP, I did this via Cygwin, which is the official route to git on Windows.
To actually be able to use git-svn, I had to install two Cygwin packages: git and subversion-perl.
I ran into some issues with the subversion perl bindings, but reinstalling subversion-perl fixed the problem.
I also needed to download Error.pm from CPAN and place it in <cygwin_root>/lib/perl5.
The final (minor) issue I hit with the installation was git-svn not being in a $PATH directory by default. (If you don’t want to mess with this, you can just say git svn (no hyphen) instead, and it’s all the same — as far as I can tell.)
All in all, the installation wasn’t a walk in the park, but it wasn’t too bad either.
Git-ting The Project
As I mentioned, the code I’m working on is an inner module for a larger piece of code. I toyed with the idea of trying to git the whole thing, but making the svn:externals definition work out seemed like it would be complicated at best. So, for now, I removed the externals definition on my local copy and checked out the inner module directly. (I’d be interested to hear about other ways to handle this.)
To do the checkout, I first prepared a directory:
git-svn init -s http://url.of.the/subversion/repository
(The -s means “stdlayout” — the svn repository has a normal trunk/branches/tags layout. The docs have more info on the different options).
Then to actually grab the repository:
git-svn fetch
Git stores the entire project history along with each repository (see the git tutorial if you want to know more about git), so the fetch can take a long time. This step took about 6 hours to get the ~12k revisions in my project.
If you don’t care about having the whole history, you can tell git to use any revision number as a starting point:
git-svn fetch -rREVISIONUsing It
At this point, I could start using normal git commands to manipulate my local repository. To try it out, I created a local branch to do some work in:
rdickerson@rdickerson $> git branch -a * master rdickerson@rdickerson$> git checkout -b aa_cache_fix Switched to a new branch "aa_cache_fix" rdickerson@rdickerson $> git branch -a * aa_cache_fix master
(Again, see the git tutorial if you’re confused).
I made the changes I needed and committed back into the task branch:
rdickerson@rdickerson $> git commit -a
At this point I needed to merge back into the master, but I wanted to consolidate all the incremental changes I had made in the task branch into one big commit I could pass back to subversion. To bundle all of my branch commits together, I used the --squash merge option and made the large single commit to the master branch:
rdickerson@rdickerson $> git checkout master rdickerson@rdickerson $> git merge aa_cache_fix --squash rdickerson@rdickerson $> git commit -a -m "Fixed AA Cache"
Then I made sure my project was up-to-date and pushed the changes back out to subversion (the lines = redaction):
rdickerson@rdickerson $> git-svn rebase Current branch master is up to date. rdickerson@rdickerson $> git-svn dcommit Committing to --------------- ... Authentication realm: ------------------ Password for '---------': M ------- File #1 M ------- File #2 Committed r12457 M ------- File #1 M ------- File #2 r12457 = 09121633e5ca898cc96cd4f2264c987c7f29fc0f (git-svn) No changes between current HEAD and refs/remotes/git-svn Resetting to the latest refs/remotes/git-svn
And my commit shows up in both the git and subversion logs. Hooray!
Idea Integration
There are a couple Idea git plugins available, but none of them seem 100% perfect. I went with git4idea, which seems to be the standard.
Idea lets you specify version control systems on a per-directory level, so using git for my inner module and svn for everything else was no problem:

The plugin has a nice, simple interface for switching branches:

Similar things exist for merging, stashing, pushing, pulling, etc.
I did run into some issues after I created a new file, added it to git, then renamed it — everything looked great through the console, but Idea’s file statuses were messed up, even after using the “Synchronize” and “Refresh” commands. I had to reopen the project to get things right again.
Another minor thing is that the commit dialog has no indication of what branch you’re in, so it would be pretty easy to accidentally commit to the wrong branch.
Impressions
So far, using git locally has been great. I can:
- Create, switch, and merge branches quickly and easily
- Perform basic git operations from Idea
- Make commits and view project history even if I’m working offline or the subversion server is down. (Which admittedly happens rarely).
Keep in mind it’s only been two days, so who knows how I’ll feel after using it for a while. So far, though, I’ve learned a lot about git and set myself up with a swank local VCS in the process, so I’m going to say it was worth the effort.