GIT and SVN interoperability or moving from SVN to GIT without loosing history

10 Sep 2019 - tsp

Normally git and svn is viewed as a competing solution for source control. But in fact git and svn just serve different development models and provide different features. In fact there are situations where git is more suited and also situations where subversion is.

Note that this article is only focusing on the interoperability between git and svn. If you want to know more about git you can take a look at my git cheat-sheet or read a full book on all techniques and the theory behind version management with git like Version Control with Git: Powerful tools and techniques for collaborative software development (note: Amazon affilate link, this pages author profits from qualified purchases).

The main difference between SVN and GIT is that GIT tries to model a distributed non centralized development process wheras SVN defines that there is a single ground thruth to all history and current state of the project, the centralized repository. This leads to some differences:

When do you want to use SVN and when GIT? If you have a centralized strictly managed workflow that requires a single true history and a simple client - use SVN. If you require distributed development features, offline repositories or like the idea of local branches on developer machines, multiple remotes, signed commits, etc. - use GIT. In case you are unsure use GIT - but be prepared to read a little more onto it’s usage and play around a little bit with rebases, branching and similar commands at the Learn Git Branching service.

On the other hand it might also be interesting to use a centralized SVN repository with the GIT clients on the client side - then one can use the single centralized linear repository on the server side as well as SVN client for most users - and the GIT client using local repositories, GIT features like rewrites in local branches and similar features on selected clients for advanced users.

Note that interoperability normally requires an additional package installed (for example on FreeBSD that’s the devel/git-subversion package).

Basic interoperation

There are also tools which provide interoperability - for example the git svn command. This command allows users to provide a bidirectional flow between git and subversion - or in other words one can use git as a client for an SVN repository and having the benefits of using a local GIT repository. It simply adds SVN as a remote and translates most basic features between GIT and SVN.

It can follow a standard subversion repository (especially easy if this repository follows the well known trunk, branches, tags layout for which one can supply the --stdlayout option but it’s easily adaptable to other layouts by specifying the locations via -T, -t and -b during init respectively.

Initializing the repository

To initialize a git repository with additional metadata for subversion one can use git svn init. This initializes a git repository with additional metadata. This command acceps some additional arguments:

Example:

git svn init svn://svn.example.com/reponame --username=exampleuser -T trunk -b branches -t tags

Fetching from SVN into GIT

To fetch data from the SVN remote into the local GIT repository one can use the git svn fetch command. This command accepts a few useful options:

Example:

git svn fetch

Initializing and fetching in a single step

There is a single command to initialize and fetch in a single step that’s called git svn clone. If one specified --preserve-empty-dirs a .gitignore file is created in every empty directory that is cloned from the SVN repository to prevent removal on later SVN commits.

Rebase to head

The git svn rebase command fetches revisions from the SVN parent of the current head and rebases the current uncomitted work against it. This is similar to svn update but preserves linear history (this is different to git pull and git merge to keep the history models of SVN and GIT the same).

Note that rebase requires a clean working copy.

Example:

git svn rebase

Dcommit

Commit all local branch commits to the remote SVN as single commits. This replays all local commits (optionally from a different local branch) into a remote SVN repository - one comit at a time.

git svn dcommit

One should note that dcommit changes all commit hashes - i.e. it might get problematic if these commits have already been pushed to a remote git repository. If one really wants to use SVN and GIT remotes one should always first svn dcommit into the remote SVN and then git push into the remote GIT repository.

In case of conflicts one should use svn rebase after the failed svn dcommit to move local modifications at the currently known remote head state. After this action one can resume the usage of svn dcommit.

Just use git svn rebase always before you resume working or before dcommiting.

Migrating from SVN to GIT

If it’s only about a simple repository one can simply do a git svn init followed by a git svn fetch or a combines git svn clone to check out all commits ever done on a subversion repository into a local git repository. This leads to a repository consisting of a set of commits that correspond to the linear SVN history. One can then simply attach an GIT remote and continue usage of GIT using all GIT features - if one really stops using the SVN repository from this point on.

This article is tagged: Programming, Basics


Dipl.-Ing. Thomas Spielauer, Wien (webcomplains389t48957@tspi.at)

This webpage is also available via TOR at http://jugujbrirx3irwyx.onion/

Valid HTML 4.01 Strict Powered by FreeBSD IPv6 support