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
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
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
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
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.
--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
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:
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.
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>
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.
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
Export and Import Reviews
Or a tea, water, soy milk. Or take a healthy walk. ↩︎
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. ↩︎
That’s indeed true for all other commands run repeatedly. Lean towards automation to gain the freedom to do the actual work. ↩︎
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. ↩︎
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. ↩︎