I knew I wanted my company to make the switch from SVN to Git, for a number of reasons:
- I had been using Git with Github for a while and it felt good.
- Our workflow with Subversion was dysfunctional in that no one could commit until code was ready for production.
- We never branched with Subversion, so working together on a project was painful (emailing patches, yikes).
- Our Subversion server is in the basement, that sometimes floods. We could have lost all that stuff.
Windows
My fellow developers and I live in a Windows environment, which is not impossible to Git-ify, but it’s certainly more challenging than if we were a bunch of bash geeks.
- When making the switch, I had to be sensitive to how my fellow devs would use GUIs to interact with our repositories.
- Pulling our Subversion repository down into Git was very slow on Windows, which meant using a Linux virtual machine to get things started.
git svn clone
The first step was to pull the Subversion repository down into a Git repository by running git svn clone
. I followed this awesome guide to perform the following:
- Retrieve a list of all Subversion committers
- Clone the Subversion repository using git svn
I took one look at our Subversion repository and knew right away that I couldn’t use the --stdlayout
flag to pull branches, tags, and trunk. Our repository was all over the place, and it had been moved around a lot over the years, which meant that we would lose commits. I decided to just pull down everything and break things out later.
We lost commits
It’s true, any commits that took place before directories were moved within our repository are no longer part of the history of those directories in Git. We made a decision to let those earlier commits go, rather than figure out a way to get them back. We might just run SVN forever in case we really need to go back.
git-svn died of signal 13
Our Subversion repository is 63,000 commits, which Git had to churn through and transform into Git commits. This was a very long churn (way longer on Windows). Eventually, git svn croaked. The good news is that you don’t have to start over when this happens. Performing a git svn fetch
will continue where git svn died. I used while ! git svn fetch ; do sleep 1 ; done
from [http://stackoverflow.com/a/13246655/2097613] to get further longer, but even this would eventually die. It took about 12 hours to git svn clone 63,000 commits on a Linux VM with four cores.
git svn fetch
When we were ready to make the big switch, I did one last git svn fetch
on the repository to get the latest SVN changes before moving to Git. I saw commits pull in and thought everything was great. But wait! Running a git log
showed that I was missing the last 100 commits, and there was no way (that I could figure) to get those in. I had to start all over again, with a 12 hour long git svn clone
. I’m not sure what happened, but I’m assuming that I did something to disrupt git svn
in my experimentation, perhaps when I was playing with converting svn:ignore into .gitignore and then reverting.
git_split
Our Subversion repository was a beast. I used a handy little script to split directories in my Git repository out into their own bare repositories, complete with all the change history. It was this process that made me learn about the difference between bare and working repositories.
The Workflow
I work with about ten developers, most of whom are comfortable in a GUI-based environment. I wanted the switch to Git to be beneficial for everyone, and I wanted to avoid disruption, if at all possible. I gave two presentations in two weeks: an intro to Git, and then a workflow presentation. I wrote up a very long guide, describing every action that anyone might want to take with Git, using EGit (the Subclipse Git counterpart for Eclipse) and TortoiseGit.
In retrospect, I don’t think I could have possibly known what would happen when we flipped the switch. A whole plentitude of issues arose immediately.
- LF to CRLF conversion: When installing TortoiseGit, some people had chosen different configurations for handling LF to CRLF file conversion. After the switch, we decided to turn off conversion for everyone, which made a ton of dirty files in everyone’s working copies. Fixing this mess was not a piece of cake.
- Deployment: Our production server is a working copy, so our typical deployment was a matter of looking at differences in Tortoise SVN’s lovely Check for Modifications tool and then updating the files we wanted. With Git, this process turned into a fetch then a diff then a pull, pulling everything of course, all with password prompts.
- Branching: Although I encouraged people to start branching, it became clear very quickly that branching was not optional. In retrospect, I would have pushed branching sooner in the switch.
- Dirty working copies: I thought it would be fairly seamless to copy the Git repository over existing working copies so that dirty files could remain dirty, but for everyone who did not have a starting clean repository, there were issues that weren’t easily resolved.
- Conflicts: I didn’t realize there would be so many conflicts right off the bat. I was not prepared to help my fellow developers get through conflicts in EGit or Tortoise Git. We made some mistakes when resolving conflicts that resulted in accidentally reverting the repository, sending old files back out to production, and generally breaking stuff all over the place.
The Good News
Yes, the switch was challenging, but so, so satisfying. I knew there were reasons to move, but I don’t think I realized how awesome it would be to have our version control in Git.
- Everyone’s branching! We have branches all over the place!
- People are committing! There’s no reason not to commit anymore, and this feels great!
- Bitbucket is excellent. We haven’t been able to scan through code in a browser in a long time and this is extremely convenient. Also, I needed support a couple of times and Bitbucket was responsive and helpful. And one more thing, Bitbucket’s integration with JIRA is SWEET.
- A deployment tool! Finally, switching to Git and the pain of deployment was enough to get the resources I needed to make a long-time dream, push-button deployment, a reality at my company.
It’s been about three weeks since we moved to Git, and everyone’s gotten into a comfortable flow. It was total chaos for about a week, and then things worked themselves out. I cannot thank my fellow developers enough for their patience and their help. From quickly written file system scripts to mass reverts, from work on the deployment tool to saving me when I felt overwhelmed. I love my job!
Resources
Here’s just about everything from my SVN to Git bookmarks folder:
- Cleanly Migrate Your Subversion Repository to a Git Repository
- Converting from Subversion to Git
- How to migrate SVN with history to a new Git repository
- Converting a Subversion repository to Git
- Converting an SVN repository to Git
- How to update git log after git svn fetch on a bare repo
- Issues with git-flow
- Move all new code on master to a new branch in Git
- From SVN to Git: How Atlassian Made the Switch