Feb 012009
 

There are some masochists around still using subversion. If you have to deal with their work somehow, your must-use tool is git-svn. This is a bidirecteral gateway between git and svn – it allows you to fetch entire svn repositories into your git repositories, then enjoy working with git, and later push your changes back to original svn repositories if needed.

Although there is some fine documentation on using git-svn, I still think the below tips may be useful for someone who just needs to set up import, and then forget that svn exists. Like in a common debian-packaging case.

The below example presents details on importing eina component of enlightenment svn repository into debian pkg-e team’s git repositoriy at alioth.debian.org.

Doing initial import

Better to do initial import into a local git repository, and not directly to repository on server, to avoid breakages if things go wrong.

  • Cd to the local repo directory (either an empty repo created by git init, or to repo that already contains previous packaging work).
  • If repo is a bare repo (i.e. git data is in the repo directory itself,
    not in .git/), set GIT_DIR environment variable to point to the repo directory. Without this hint, git-svn can’t work with bare repos.
  • Initialize git-svn:
    git svn init --trunk=trunk/eina http://svn.enlightenment.org/svn/e

    The git-svn init command line tells git-svn where svn repository is, and what part of it should be fetched. Documentation has some details.

  • By default, git-svn does not prefix remote git branches that it creates with svn/, which is ugly, especially when you have other (non-svn) remote repos tracked in your local repo. Better to fix that before initial import. To do that, change the value of git config svn-remote.svn.fetch:
    $ git config svn-remote.svn.fetch
    trunk/eina:refs/remotes/trunk
    $ git config svn-remote.svn.fetch trunk/eina:refs/remotes/svn/trunk
    $ git config svn-remote.svn.fetch
    trunk/eina:refs/remotes/svn/trunk

    You may edit .git/config file directly as well.

  • Do the import:
    git svn fetch

    First run of this command may be extremely slow (several hours, even days on slow connection) and traffic-hungry, since it will fetch entire svn history. Later updates will be fast.

Once these steps are completed, you have entire svn history in your git repo, so you may browse it using gitk, branch from whatever point, or push it to another git repo. More on this below.

To fetch svn updates into your repo, just run git svn fetch periodically.

Moving git-svn import to another repo

Once svn import is done into your local repo, svn/* branches may be pushed to another repo in the same way as any other git branches.

However, to make git-svn working on remote repo (without redoing time- and traffic-consuming initial import there), two additional steps are required.

Before pushing, login into remote server, cd to the repo there and/or set GIT_DIR environment variable, and initialize git-svn using exactly same git-svn init command line as you did on your initial import. Also do exactly same svn-remote.svn.fetch adjustment.

Then do the push:

git push ssh://alioth.debian.org/git/pkg-e/libs/eina.git refs/remotes/svn/*:refs/remotes/svn/*

In your setup, remote repository location will be likely different, but refspec should be the same.

Once import completed, login into server, cd to the repo there and/or set GIT_DIR environment variable, and run git svn fetch once, to make it rebuild it’s metadata. Git-svn stores needed info inside log messages of the imported commits, so metadata rebuild is a local operation and runs fast.

Now git-svn may be used on the remote server.

Warning: git-svn does not like when it’s branches are updated by other git commands. So don’t mix updates of those branches with git fetch and with git svn fetch – choose one of these two and use only that. If you have ocasionally updated svn/* branch from remote git repo with git fetch, you may restore git-svn functionality by removing git-svn metadata (stored in hidden files in branch directories under .git/svn/) and running git svn fetch to restore it. If that does not help, it is possible to remove all tracks of git-svn from local repo (.git/svn directory and svn-related sections in .git/config), and then move things from remote repo to local repo, exactly as described above, but in the reverse direction. Git is smart enough not to copy objects that are already in your repo, so this is even faster than you could think :) .

Setting up auto-import

Once git-svn import is on server, it is easy to set up auto-import, such that server will have a (non-remote) git branch that follows svn trunk.

We do it by having an hourly cron job on server, that runs something like

export GIT_DIR=/git/pkg-e/libs/eina.git
git svn fetch
if ! git push $GIT_DIR refs/remotes/svn/trunk:upstream-vcs; then
  git branch -D upstream-vcs
  git branch upstream-vcs svn/trunk
fi

Normally, it just fetches updates from svn, and fast-forwards local upstream-vcs branch with the fresh fetch. But if fast-forward fails (which may happen if someone occasionally changes upstream-vcs branch), then branch is deleted and re-created at current svn/trunk point. (This “rude way” is only executed in problem case, not always, to avoid having a window when upstream-vcs branch does not exist.)

Once this thing is set up, we no longer care that upstream is using svn. We have all their updates in our git. And that is cool.

Sorry, the comment form is closed at this time.

© 2011 yoush.homelinux.org Suffusion theme by Sayontan Sinha