December 11, 2013
Often when working with clients, I do not have the luxury of choosing my tech stack and using preferred tools. One of my recent challenges has been dealing with a Subversion repository for version control. I decided to integrate git-svn into my workflow in order to add a little more sanity to my day. Below are details of the basic setup and some of the questions I encountered during my adventure with git-svn.
This assumes you have git-svn already installed. To be sure it’s available, run this at the command line:
$ git svn --version git-svn version 126.96.36.199 (svn 1.6.18)
If not available, you will need to upgrade your version of git.
Clone the repo
To start, we will clone the remote svn repository. This will take as long as you have svn revision history for the entire repo. Adding the -r option will only grab history from a specific revision forward. The -s options indicates my svn repository has the standard layout of trunk, tags, and branches.
$ git svn clone <the_svn_repo> -s
Working with master (a.k.a. trunk)
By default, the master git branch is mapped to svn trunk. The master branch is mapped to the svn trunk.
$ git branch * master
Make changes to trunk/master:
$ touch some_file $ git add some_file $ git commit -m "Adding some_file"
At this point, changes are in your local git svn master branch. To push these changes to the remote svn repository:
$ git svn dcommit git svn dcommit Committing to file:///the_svn_repo/trunk ... M some_file Committed r8 M some_file r8 = 3c16f3e39bc53c536a840060f4cbff2b98cba630 (refs/remotes/trunk) No changes between e9c6be90d53f7ece289533e2ff559a646a9d1b3b and refs/remotes/trunk Resetting to the latest refs/remotes/trunk
dcommit pushes the changes from your local git svn branch (in this case master) to the remote branch (in this case trunk). Similar to svn commit.
Working with branches
To see what remote branches you can switch to:
$ git branch -r branch1 branch2 tags/tag1 trunk
To fix a bug on an existing remote svn branch, create a new local branch based on that remote branch.
$ git checkout -b bugfix branch2
Make your changes to the bugfix branch:
$ touch some_file $ git add some_file $ git commit -m "Adding some_file to bugfix branch"
At this point, changes are in your local git svn bugfix branch. To get these changes into the remote branch, dcommit.
$ git svn dcommit Committing to file:///the_svn_repo/branches/branch2 ... A some_file Committed r10 A some_file r10 = c1f3dbbc1704aaa1406798ee784e9375b4c590c5 (refs/remotes/branch2) No changes between 82b8c93d98ff9975d6981cd56198a06b93b4e132 and refs/remotes/branch2 Resetting to the latest refs/remotes/branch2
dcommit pushes the changes from your local git svn branch (in this case bugfix) to the remote branch (in this case branch2). Similar to svn commit.
How do I get updates from the remote svn repository?
This will fetch updates for the current branch and replay your local commits on top. It is similar to svn update.
$ git svn rebase
How do I know what branch I will dcommit to?
Running dcommit with the —dry-run option will pretend to dcommit the changes, but instead print out the diffs that will be committed to svn.
$ git svn dcommit --dry-run Committing to file:///the_svn_repo/trunk ... diff-tree 2bb32345fae045037c125d520bbb8b770e5cf5cb~1 2bb32345fae045037c125d520bbb8b770e5cf5cb
The result can then be used to view a diff of the change:
git diff-tree 2bb32345fae045037c125d520bbb8b770e5cf5cb~1 2bb32345fae045037c125d520bbb8b770e5cf5cb -u
Just don’t forget the -u at the end of that command.
How do I get my svn and git-svn ignores configured?
The following will shove all the svn:ignore metadata into the .gitignore file which you can then version control. The .gitignore file will need to be maintained using this command as svn:ignore metadata will occasionally change in the remote svn repo.
git svn show-ignore > .gitignore
This file can then be committed to the repository. If you prefer to not pollute your remote svn repository with git metadata, you can also add .gitignore to the .git/info/exclude file. Each developer using git-svn will need to do this and maintain their own .gitignore file. show-ignore can be slow and painful so committing it is recommended.
… for the moment. Stay tuned for a future post detailing how to “catchup” your branch with master/trunk and “reintegrate” it back into master/trunk.