An Introduction to git-svn
Table of Contents
The majority of projects these days still use Subversion to manage their source code – true to the motto “never change a running system”. Thanks to “git-svn”, however, you can still work with Git locally in such projects.
With git-svn, you can create a Git clone from any Subversion repository, make changes, and commit those changes back to SVN without anyone knowing that you did not use a pure SVN client.
Cloning SVN repositories
To clone an SVN repository, just provide the URL of the SVN repository (along with your credentials if the SVN repository requires authentication).
If the directory layout of your SVN repository does not follow the SVN standard directory layout (trunk, branches, and tags directories), you need to provide additional path information on where your main branch, branches, and tags reside so git-svn can create remote branches for them.
You need to be patient: Cloning a large SVN repository can take some time as git-svn needs to import all revisions.
Here is the one thing you should be aware of if you do not want to annoy SVN users on the other side of the repository:
If you create branches in Git to make your changes (probably the reason why you have chosen to work with git-svn), you have to either squash-merge your changes back to the original branch or rebase with the original branch before merging. If you squash-merge, you will lose individual commits while rebasing will preserve them.
Let us take a look at an example: You create a new branch develop from master and add two files FOO and BAR in two separate commits. If you merge them back and a merge commit is created, only the merge commit itself will be visible to other SVN (or git-svn) users.
The following two images show the history as it appears in the Git repository and in the SVN repository after both repositories have been synchronized.
As you can see, all changes will be there, but the individual commit information is lost as SVN will never receive and thus not know about the commits of the other branch.
Synchronizing with an SVN Remote
Synchronizing with SVN remotes pretty much works the same as with a Git remote. You can fetch, pull and push changes.
The only twist is that each local branch is tied to the SVN remote branch it was derived from. For example, if your local branch master was created from the SVN remote branch trunk, they will be tied forever by the git-svn-id line that every local git-svn commit carries in its message. This git-svn-id line contains an SVN repository identifier and the full SVN URL along with the SVN revision it corresponds to. It is probably a good idea to set up Git branch tracking between your local Git branch and your SVN branch so you will receive information about commits ahead and behind.
If you create new commits, they will be missing the git-svn-id. This is because they are not yet associated with an SVN revision as they have not yet been pushed. Once you successfully push them to the SVN repository, each commit you have made will be rewritten locally with the git-svn-id.
Another thing worth noting is that git-svn will always rebase your local branch with new revisions from the SVN repository (e.g. pull --rebase). This is done to preserve SVN’s linear revision history, which rebase is all about. If you are not familiar with Git’s rebase, it may be a good time to dive into this topic first.
Just like in Git, it is a good idea to check for changes and pull them in before pushing to an SVN remote. git-svn will automatically update your current HEAD with the latest revisions if you have not already done so. However, if there are conflicts while rebasing, push will be aborted and you will have to resolve the conflicts and push again–so it is probably more convenient to pull first.
With git-svn, the information about ignored files will be managed on the SVN remote. You can fetch this information from the SVN remote repository and add them to your local ignores.
In Tower, right-click on the remote and select “Add SVN Ignores to Exclude File Patterns”. After the ignore patterns have been fetched from the SVN remote, they will be added to your .git/info/excludes file.
Subversion identifies users only by their username, not by their full name and email address as in Git. By default, git-svn will create Git commits with just the username from SVN as Git author. New commits in Git will have your full Git user information but once you have published them to the SVN remote, this information will be replaced by the user information from SVN.
There are ways in git-svn to set up a mapping from SVN usernames to Git users, but none of these approaches (or any other) offer a viable solution to gain fully mapped author information (and that is why Tower does not provide support for configuration of author name mapping).
Pruning obsolete SVN remote branches
Pruning obsolete SVN remote branches will not work in git-svn. In fact, you may find remote branches on your SVN remote that even do not exist on the SVN remote any longer as git-svn preserves a reference to any remote branch ever created on an SVN remote.
Deleting branches or tags on the remote SVN repository
git-svn does not support deletion of branches or tags on the remote SVN repository. You can create them, but you cannot delete them.
Relocating an SVN repository URL
Relocating the SVN repository URL is not supported by git-svn. The reason for this is that git-svn stores the SVN repository URL in each commit and relies on this information. If you wanted to change the SVN repository URL you would have to rewrite the entire commit history to change the URL in each commit. You would also have to completely rebuild the SVN metadata. If you do not have any pending commits, just re-cloning the SVN repository is probably much more comfortable.
Another option is to add a second SVN remote repository with the new URL and then migrate your changes from the old branches to the new ones by stashing or cherry-picking single changes.
If you have not tried Tower yet, you can download the latest version and give it a try.