New versions of git make the information on this page obsolete.
Please see my new post about this.
There are plenty of tutorials and blog posts out there regarding how to move from subversion to git smoothly. In those, the goal is often to keep svn as the public frontend but to spend most of the day in git, only interacting with svn through
git-svn. My goal here is a bit different: I want to permanently move all my code to git and get rid of the svn repositories after the migration is complete. In the process, I want to cut my svn repositories in small pieces and make each of those a separate git repository. This involves
git-svnimport and the steps are described below.
To work with something more concrete, here is my svn layout. The blue lines are repositories, i.e. version numbers are common to everything inside those. Green lines are projects inside a repository. Each project has the canonical svn layout with trunk/branches/tags directories. Inside the trunk, several directories are present and separate different aspects of the project (e.g. source code and documentation, articles and posters here). This layout is the classic one described in the section “Planning Your Repository Organization” of the svn book. The first requirement is to move the history and tags to git (I rarely used branches and, when I did, they disappeared quickly after being merged to the trunk). In addition, after working with this layout a few years, I now feel that things like code and documentation should have been two separate projects, possibly separate repositories. Because svn makes it complicated to set up new repositories (requires access to the server) but easy to check out only a part of the repository, you might also have preferred the “one-big-repository/several-projects” approach, as I did. In my case it means that I want
ownfor/bbscript/src to become one git repository and
ownfor/bbscript/doc to be a separate one.
What does not work
Now git offers two interfaces to svn repositories
git-svnimport. Most people (web, git’s IRC room, etc.) recommend
git-svn. To fetch the full trunk/tags/branches hierarchy of a project you would
git svn clone $SVNROOT/ownfor/bbscript/
While this keep all the information regarding tags and branches what you typically would like to do is get only the trunk as visible files on your disk and get the tags and branches as some kind of meta information inside git (i.e. in .git). This should be doable this way
git svn clone -s $SVNROOT/ownfor/bbscript/
-s arguments tells
git-svn that the project (
bbscript) is organized according to the standard trunk/branches/tags hierarchy of svn. This fetches only the trunk but seems unable to translate svn tags into git tags, at least on my system.
Plus, I am only interested in a subset of
bbscript. I can of course import only
git svn clone $SVNROOT/ownfor/bbscript/trunk/src
but then it obviously cuts
src from its tags and branches, which would be in
../branches, together with those of
Finally, one can still use
git-filter-branch to isolate
src only, from a full project checkout. However, the man page of
git-filter-branch is not really encouraging for a newbie:
WARNING! The rewritten history will have different object names for all
the objects and will not converge with the original branch. You will
not be able to easily push and distribute the rewritten branch on top
of the original branch. Please do not use this command if you do not
know the full implications, and avoid using it anyway, if a simple
single commit would suffice to fix your problem.
What does work
On the other hand,
git-svnimport seems to be more suited for one-time, read-only imports as I want to do. From the man page
git-svnimport – Import a SVN repository into git
Imports a SVN repository into git. It will either create a new
repository, or incrementally import into an existing one.
The syntax is
git-svnimport -P <path_from_trunk> <SVN_repository_URL>
<path_from_trunk> part allows to import only a specific directory from trunk, along with all tags and branches which intersect with this directory. In my case, I can use
-P src to import
src and the tags regarding the source code, but not the tags regarding the documentation, which is exactly what I want.
<path_from_trunk> is only appended to the trunk/tags/branches part of the path which itself, is supposed to be right after the
<SVN_repository_URL>. So basically
git-svnimport supposes svn repositories to be organised as
while most are probably organized according to the svn book’s advice
The trick is to use the options
git-svnimport to specify the path to the trunk, banches and tags, including the project name. So, keeping in mind the layout of my repository, to get a fully independent git repository of the src folder in the bbscript project of the ownfor svn repository, I used the command
git-svnimport -v -T bbscript/trunk -b bbscript/branches -t bbscript/tags -P src file:///Users/jiho/svn/ownfor
This was a long post to get to this point but reporting the train of thought that lead to the decisions might be interesting to some.
PS: I considered Bazaar (bzr) as a possible alternative to Subversion. Its simpler feature set as well as workflow model seemed better suited for me. However, on other projects, I already got used to some of git niceties that are not easily available in bzr, such as coloured output, built-in word diff for LaTeX files, git-gui (even if it is butt ugly), etc. Moreover, the bzr-svn plugin only works with bzr > v1.6 (I only have easy access to 1.5 through Macports) and does not seem as advanced as git’s tools. Finally, bzr as a plugin to import git repositories while the reverse is not true. So I will be able to switch to bzr eventually if I want to, while I would not have been able to switch from bzr to git.