If you use the amazing git-svn to work in a civilised manner with a subversion repository, you may have trouble if the subversion repository is relocated, ie. has its access URL change. This article describes an approach for handling this situation, which git-svn does not directly support.
git-svn relies heavily on the SVN URL
Every svn commit that is found in a git-svn repo has a ‘git-svn-id’ tag associated with it, and which is included in its commit message. This tag is built partly from the URL of the svn repository from which the commit came.
The same physical svn repository leads to different git-svn clones if it is served via different URLs. Relocating is therefore a problem, and is not - as far as I am aware - supported in any fashion by git-svn. That seems a reasonable decision, since the changes in a codebase managed by git-svn are expected to be coordinated via SVN, so the git-svn repositories should be largely disposable.
However, if a user has local changes in his git-svn clone that he does not wish to lose, he must find a way to preserve those changes in his git-svn repository after the svn repository has been relocated.
An approach that worked for me
The svn repository of a large codebase upon which I work was recently relocated, and I wanted to keep working with my git-svn clone. In particular, my git-svn clone had a few local branches corresponding to pending work that was not yet committed to svn; I wanted to preserve the content of these branches.
I achieved the desired effect by following these steps:
- Create a new git-svn clone from the new svn URL
- Copy local branches from the old git-svn clone to the new clone
Creating a new git-svn clone should be familiar to any reader to which this article is relevant. Copying local branches is more involved…
Copying local branches between git-svn repositories
Let’s walk through the process of copying local git branches between two git-svn clones of the same svn repository.
Starting in the ‘old’ repository, we find local branches. Those are the branches where the head is not in svn:
1 2 | |
Just one branch. Let’s see how to recreate that branch and its contents in the new clone.
We’ll need to find where the branch started. Let’s find the last revision on the branch that had a git-svn-id:
1 2 | |
It seems safe at this point to assume that this was the branch point. We can find the svn revision as follows:
1 2 | |
Now we need to find that revision (7783) in the new git-svn clone:
1 2 | |
Cool, so we create a branch at that point in the new repository:
1 2 | |
And finally, we need to slurp all the non-SVN commits from the branch in the old repo into the new branch in the new repo. The combination of git-format-patch and git-am are perfect for this:
1
| |
Voilà! The local branch has now been copied and committed into the new git-svn clone repository.
Wrapped up in a shell script
Update: Here’s an updated script in Ruby provided by Ed Ruder, which works with the current git as of Sept. 2010.
Here’s a shell script that I chose to name “git-svn-copy-local-branches”:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | |
Conclusions
Thanks to the rich set of git commands, it’s possible to easily graft branches between compatible trees of commits. Using this technique, we can preserve our work even if we have to re-clone an svn repository.