Tarin Gamberini

A software engineer and a passionate java programmer

The Best of Git working with Subversion

Usually to interact between a remote Subversion repository and a local Git repository you have to be on the local master branch and run:

  • git svn dcommit instead of git push
  • git svn rebase instead of git pull --rebase

There is no equivalent to git pull because Subversion and Git handle merges differently, so to prevent Subversion committers saw merge commits a rebase is mandatory.

You can get the best of Git working with Subversion interacting between the Git local repository and the local working directory.

So you can:

  • preparing to commit only the part of a file you want, by using git add --patch
  • rewriting commit history, by using git rebase --interactive and the various pick, reword, edit, squash, fixup
  • extremely quickly create new branches
  • including in the current branch a single commit made on another branch, by using git cherry-pick
  • using git bisect to find which commit caused a particular bug
  • temporarily parking last changes to face an emergency, by using git stash save my_current_issue

and do all the other stuff you can do locally that make you love Git.

I want to stress about using local branches to your benefit only and not to collaborate with other committers. This means you have to merge locally your branches into master before interacting with remote subversion repository. In this way no one could see your merge commits.

Anyway to work with a remote Subversion repository tracked by a local Git repository you need to do some preparatory work: let’s go.

Mapping authors

In Git every committer is identified by a username and an email address.

The --authors-file=<filename> git svn option lets you associate every Subversion committer username with the appropriate email address.

In order to get an automatically generated <filename> to be used whith the --authors-file option you can use the following git_svn_authors_extractor.sh bash script:

git_svn_authors_extractor.sh
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
echo
case $# in
    0) echo NAME
       echo         $0
       echo
       echo SYNOPSIS
       echo         $0 URL
       echo
       echo DESCRIPTION
       echo         Generate a formatted list of committers name, with
       echo         associated email, who have committed on the remote
       echo         SVN repository identified by URL,
       echo         eg. https://example.com/svn/project .
       echo
       echo         You MUST have previously installed a SVN client.
       echo
       echo SEE ALSO
       echo         SVN log documentation: you can get it by running "svn log -h".
       echo
       echo AUTHOR
       echo         Tarin Gamberini - www.taringamberini.com
       echo
       echo LICENSE
       echo         GPLv3 or any later version
       echo         http://www.gnu.org/licenses/gpl-3.0.en.html
       exit ;;
esac

authors=$(svn log $1 -q | grep -e '^r' | awk 'BEGIN { FS = "|" } ; { print $2 }' | sort | uniq)
for author in ${authors}; do
  echo "${author} = NAME <USER@DOMAIN>";
done

The script expects as first argument a remote Subversion repository URL.

To get a newly created authors file run at command line:

$ sh git_svn_authors_extractor.sh https://example.com/svn/project > project_authors_file.txt

If Ann and Bob were the committers' username on the remote SVN repository https://example.com/svn/project you would get a project_authors_file.txt file which contains rows like these:

Ann = NAME <USER@DOMAIN>
Bob = NAME <USER@DOMAIN>

where you have to edit NAME and USER@DOMAIN as you whish.

Time ago the solution of automatically extract the authors username directly from Subversion solved me a sly problem with encoding. The Subversion repository was hosted on a GNU/Linux machine whereas I was working on a Windows machine. I ran something like svn log https://example.com/svn/project which printed a username like name_surname. So I manually wrote name_surname in a newly created project_authors_file.txt, but the cloning process aborted saying that no name_surname were found in authors file: I was really shocked!

Cloning SVN repository

The following command will create a local directory called project syncronized with the remote trunk/ directory:

$ git svn clone --stdlayout --prefix=origin/ \
    --authors-file=project_authors_file.txt \
    https://example.com/svn/project

where:

  • --stdlayout tells Git that SVN repository has standard layout: trunk/, branches/, and tags/
  • --prefix=origin/ (the trailing slash is very important) makes SVN-tracking refs refs/remotes/$prefix/ compatible with Git’s own remote-tracking ref layout refs/remotes/$remote/
  • --authors-file=project_authors_file.txt tell git svn to abort cloning if a committer name that does not exist in the authors file is encountered

In project directory you’ll find everything but empty directories, because git doesn’t track empty directories.

The cloning process creates a real an almost real Git repository, therefore you can visualize it with your favourite graphical tool, eg. GitX.

To create a real Git repository there remain few things to do. So if you are interested about it read How to migrate from svn to git.

Ignoring what SVN ignores

Then you would like Git ignored the same file SVN ignores on that project. You can do that by running:

git svn show-ignore > .gitignore

where .gitignore is the file Git reads to ignore files and directories.

Well done: you are ready now!

Now you are ready to start working locally with Git even if the remote repository is Subversion.

There are lots of good guides in Internet which help you working with git svn so search for them, here you are some:

Post a comment

A comment is submitted by an ordinary e-mail. Your e-mail address will not be published or broadcast.

This blog is moderated, therefore some comments might not be published. Comments are usually approved by the moderator in one/three days.