Working with Git is a much more pleasurable experience than Subversion once you get used to the differences. Still, SVN has its benefits and it can be tricky to migrate existing repos and users to a new platform.
Luckily Git includes a set of tools that allow you to use Git to manage a working copy of an SVN repository. You work with Git in your project but push up changes to the shared SVN repo. So you get the benefits of working with Git daily without ditching your existing SVN repos.
Why Do This?
On a side note, I started experimenting with git-svn for practical reasons. In WRDS we have a fairly large repository for our web site that’s accessed by developers, data specialists, and non-developer professionals. The repo serves the team well. But it was created initially without the conventional /trunk /branches /tags directory layout.
I’m working on concurrent projects and needed to branch my code to easily switch between working changes. But since Subversion branches are created on the server side it would be tricky to do.
Using git-svn lets me create branches locally in my working directory without affecting the shared SVN repo. In the future, it might be worth the effort to redesign our shared repo. For now though git-svn gets me what I need with minimal disruption.
Basics of git svn
Getting started with git-svn is as easy as this command, similar to an svn checkout.
git svn clone http://wharton.unfuddle.com/svn/AllIDoIsWinWinWin
After that you can run normal Git commands against the working copy.
git status .. vim WinWinWin.html vim NoMatterWhat.html .. git add . git status .. git commit -m'Added a file to the project'
Pushing Commits to SVN
The commit command does not commit to the SVN repo the way that an SVN commit would. Instead it works just like Git committing only to your local repository. When you are ready to push your changes back up to the SVN repo you call the following:
git svn dcommit
This pushes up every commit from the Git master code line up to the linked SVN repo as an individual SVN commit.
If you’ve done work in Git only branches and merged them into the master line, only the changes you merged in will be pushed up. Unmerged changes will not be pushed up.
Pulling Updates from SVN
You’ll also need to pull down from SVN to get the latest changes from your teammates. That’s done with this command, similar to svn pull:
git svn rebase
The initial pull takes a long time
The git svn clone command polls SVN for each historical commit and creates a local corresponding Git commit. This takes a long time.
Slow on Scorpio-Dev, blazingly fast locally
After the initial pull down, things are really fast. Just like SVN though, Git relies on files for tracking repository history. And just like SVN, Git operations can be very slow over network file shares particularly on Scorpio-Dev.
On a sizeable file share repo, git status can take a few minutes to complete. The same is true for svn status calls though. My advice is to work on your desktop if you can to avoid the lag. If you can’t, you’ll have about the same lag as you would with SVN.
All commits you make to the Git master line will go to SVN. Git allows for history rewrites in various forms. So it’s a good practice to create Git only working feature branches in your Git repo, commit away on those as often as you like.
Then when you’re ready to push to SVN squash your changes down into singular commits back to the master or SVN linked branch lines. Then push from those lines back to SVN. This will help keep your master and SVN linked branch history lines clean and linear, just the way SVN likes them.
This one is important. Git svn does not automatically replicate any svn:ignore properties that you may have setup in your SVN repo. After your first checkout is done, fire off this command:
git svn create-ignore
This will replicate your svn:ignore settings in appropriate .gitignore files. You’ll then want to commit these new files to the Git repo.
Attach the -s switch to your inital clone command if your SVN repo has the conventional /trunk /branches /tags layout. Git will then create any remote SVN branches in your local repo.
You can also override these folder paths if they’re nonstandard or ignore them completely by leaving -s off if you don’t want branches pulled down. See git svn docs for details.
Permission changes flagged
If you start experimenting locally and then copy your Git repo to a remote machine then you might run into file permissions changing on your files unexpectedly. This can cause all files to show up as changed in your Git repo. The following command forces Git to ignore these changes:
git config core.filemode false
Don’t link up to other Git repos
One of the nice features of Git is linking up a local repo to multiple remote repos. If you’re connecting a repo to SVN though don’t connect to other Git repos like a Github or an Unfuddle Git repo. SVN likes its history linear and static. Git is more dynamic and introducing complexity into your history could cause major problems for SVN.