This is a story about how git-svn and a VSCode allowed me to maintain the peer-review-based software development cycle I am used to (and fond of) while working in an environment with only occasional access to the SVN-based source repository.


I give you the essential points of my git-svn workflow without boring you with an in-depth explanation of commands or even an exploration of all the options git-svn comes with. The full documentation can be found here. There exists also a nice, brief git-svn cheat sheet.

Mirror an SVN repository into a local git repository

First, we need to create a git representation of the remote SVN repository. What this means is to create a git repository where there is one git commit for each SVN revision. This implies one git branch will be created for each SVN branch that ever existed. Assuming the remote SVN repository follows the standard layout of trunk, branches, and tags, then

git svn init --stdlayout <svn-repo-url> <local-dir-to-clone-to>

Grab a coffee ☕.1 This will take a while depending on the number of revisions of your SVN repository.

Check-out a branch

Once we got the (up-to-date) repository mirror, we can start working on branches locally. First, find the remote branch to check out via

git branch -r

Once found, create a local branch that tracks the remote SVN branch:2

git svn checkout -b local/<branch-name> remotes/origin/<branch-name>

Scoping local SVN branches with sync is my personal preference: I use it solely for remote-tracking branches. For other local branches, I usually use the prefix local.

As I am bad at remembering commands, I created a VSCode task for creating remote-tracking branches. Can’t recommend that highly enough.3

Sync your work

Commit your work with git commit. As usual with git, this just continues your local git history, yet leaves the remote history untouched. Remember that our upstream branch is just a virtual git branch, and our remote as well just is a virtual git remote. Concretely, this means that git push does not work when using git-svn. Instead, we need to use two separate commands: git svn rebase and git svn dcommit.

The first syncs our git remote with the corresponding SVN branch followed by a git rebase of the local git branch onto the virtual git remote branch. Bottom line: Without (possible) merge conflicts, we are then left with a local git branch which is ahead of the associated SVN branch by just the git commits we did locally.

Once done with the rebase, it remains to perform the push operation: git svn dcommit. This creates a series of SVN revisions from our git commits, one for each git commit, in the remote SVN repository. Our work is now accessible for others using the same SVN remote as well.

Keep your git repository updated

After a period of being disconnected from the remote SVN repository, ensure to bring your local git repository in sync again. This means, getting all the recent changes from the SVN remote, converting them into git commits linked to their origin SVN revision, and, most importantly, rebasing your local branches onto the respective virtual git remote branches. Fetching all remote changes not yet present into your local git mirror is done via git svn fetch --fetch-all. Notice the --fetch-all option: it ensures you not only fetch the remote changes for your current git branch but for all remote branches.

Now you got all remote changes locally which means you now could disconnect from the remote SVN repository. Let me emphasize this point: All the history is now present again in the virtual git remote branches. Thus, all operations, also rebasing onto a remote branch, now work offline, too.

We already saw how to rebase with git-svn earlier. It brings our local git branch in sync with the virtual git remote it tracks. The earlier use, however, relied on being connected to the SVN remote. As we got all the remote information already mirrored locally, we can do better: Using git svn rebase --local not only rebases your local git branch onto its virtual git pendant but also takes all the remote information we cached already via git svn fetch.

Starting offline

Last but not least a quite common scenario: You create a new local git branch whose changes should eventually be pushed to the remote SVN. But instead of being connected to the remote SVN while creating the local branch, you are detached from it. Thus we are in a scenario [different than before][online-create-branch].

First, create your local branch:

git checkout -b <local-branch-name>

Then do your local work. Once we are connected again to the remote SVN, we create an SVN branch to push our changes onto. To do so, ensure you know the branch your local branch originated from. git svn info is of great help here, which by the way works when being offline, too:

❯ git svn info
Path: .
URL: file:///svn-playground/sample-project/trunk
Repository Root: file:///svn-playground/sample-project
Repository UUID: 9d17b593-6604-465f-acc8-010d9e58aef4
Revision: 2
Node Kind: directory
Schedule: normal
Last Changed Author: sample-author
Last Changed Rev: 2
Last Changed Date: 2022-01-03 17:26:35 +0100 (Mon, 03 Jan 2022)

Look out for URL key as it containst the branch information. Once found, create the SVN branch:

git svn branch <remote-branch-name> <local-branch-name>

The remaining step is syncing the remote-only branch into a virtual git remote branch and setting our local git branch to track the virtual one:

git svn fetch --fetch-all
git branch -t origin/<remote-branch-name>

A final git svn rebase will then bring our local git branch up to date with the remote SVN and git svn dcommit pushes our changes to the remote.

Code Reviews

We saw how to work while being disconnected from the remote SVN and how to sync our changes back. Now let us see how to do code reviews in this disconnected setup.

First and most importantly: I deeply believe that code reviews work best when everyone can participate and when participation is made seamless. A possible implementation of this belief is conversations about code right next to the code. Prime examples of this are comments in pull requests on GitHub and Bitbucket.

The best solution4 I could come up with relies on the VSCode plugin Code Review (plus a couple of PRs merged in5). In a nutshell: You can add comments on blocks of code directly from within VSCode which are stored conveniently in CSV format in your current workspace. The CSV can then be shared with colleagues, but especially the author of the code under review. In case you got a proper code review system in place, it also permits the export to some of the most widely spread thereof: GitLab and Github, but also to ticket-system JIRA.

Start a review

  • Review individual files vs. review branches
  • Make review comments
  • Pro tip: Customize your categories

Compare branches Compare commits Add a review comment

Export and Import Reviews

Select review CSV

  1. Or a tea, water, soy milk. Or take a healthy walk. ↩︎

  2. Obviously it is different than with git-only repositories. The local git branch does not directly track a remote SVN branch, but rather a virtual remote git branch. This virtual remote branch then carries the information required for git-svn to do its magic. I honestly never looked up what actually happens underneath from here on. ↩︎

  3. That’s indeed true for all other commands run repeatedly. Lean towards automation to gain the freedom to do the actual work. ↩︎

  4. To date I failed to find a solution that makes the participation seamless. Any solution, like exporting reviews locally and importing them on a remote review server for others to fetch, reviewed, again, access to a remote system. And no: exchanging code review files via emails, file shares and alike are not considered suitable IMHO. ↩︎

  5. There are currently a few open pull requests I locally merged and built the plugin from. Provider selection to add SVN revision numbers using git svn info, comment sorting in the Comment Explorer by line and column rather than by creation date, and a bag of simplifications and unifications for review-file selection↩︎