SVN2GIT(1)
π SVN2GIT β like, the manual page (part 1, bestie) π
okay so welcome to SVN2GIT(1), from the General Commands Manual. that's the manual name, section 1, we're all caught up. sit down, grab a strawberry π, we're moving your whole Subversion life into Git and it's gonna be gorgeous.
β¨ NAME β¨
svn2git β migrates from svn to git. that's it. that's the whole job. she's a little utility with one purpose and she eats every time π
πΈ DESCRIPTION πΈ
svn2git is a tiny utility for migrating projects from Subversion to Git while keeping the trunk, branches and tags where they should be. like, keeping them where they belong, not scattered across the floor of your repo like laundry, no cap.
it uses git-svn to clone an svn repository and then does some clean-up to make sure branches and tags are imported in a meaningful way β and that the code checked into master ends up being what's currently in your svn trunk, rather than whichever svn branch your last commit happened to be in. because that vibe? not it. π
π SYNOPSIS π
svn2git [-h|--help] [--rebase] [-m|--metadata] [-v|--verbose]
[--rootistrunk][--notrunk][--nobranches]
[--authors AUTHORS_FILE]
[--exclude REGEX]
[--branches BRANCHES_PATH]
[--notags][--no-minimize]
[--rebasebranch REBASEBRANCH]
[--revision START_REV:[END_REV]]
[--trunk TRUNK_PATH]
[--username NAME]
[--password PASS]
look at her. so much going on. icon behavior β¨
π OPTIONS REFERENCE π
okay here's the whole flag menu, one bullet per flag, nothing skipped, we do not gatekeep on this blog:
--rebaseβ instead of cloning a brand new project, you rebase an existing one against SVN. glow-up in place, bestie.--username NAMEβ the username for transports that need it (http(s),svn).--password PASSβ Username for transports that needs it (http(s), svn)ssword for transports that needs it (http(s), svn). π« (yes, that is literally what the page says. i am not touching it. it's part of the lore now.)--trunk TRUNK_PATHβ the subpath to trunk from the repository URL. default:trunk.--branches BRANCHES_PATHβ the subpath to branches from the repository URL (default:branches). can be used multiple times, she's flexible like that.--tags TAGS_PATHβ the subpath to tags from the repository URL (default:tags). also can be used multiple times. iconic.--rootistrunkβ use this one if the root level of the repo is equivalent to the trunk, and there are no tags or branches. the root ate and left no crumbs.--notrunkβ do not import anything from trunk. skipping the main character entirely, bold.--nobranchesβ do not try to import any branches.--notagsβ do not try to import any tags.--no-minimize-urlβ accept URLs as-is, without attempting to connect to a higher level directory. no reaching upward, we stay where we are π¦--revision START_REV[:END_REV]β start importing from SVN revisionSTART_REV; optionally end atEND_REV.-m,--metadataβ include metadata in git logs (git-svn-id).--authors AUTHORS_FILEβ path to the file containing the svn-to-git authors mapping. default:~/.svn2git/authors.--exclude REGEXβ specify a Perl regular expression to filter paths when fetching. can be used multiple times. bye to the things you don't want π-v,--verboseβ be verbose in logging β useful for debugging issues. she's telling you everything.-h,--helpβ show this message. hi, hello, here's the menu π«Ά
π EXAMPLES π
so for instance, this could be a situation in a svn repository:
trunk ...
branches
1.x 2.x
tags 1.0.0 1.0.1 1.0.2 1.1.0 2.0.0
git-svn will go through the commit history to build a new git repo. it will import all branches and tags as remote svn branches β whereas what you really want is git-native local branches and git tag objects. so after importing this project you'll get:
$ git branch
* master
$ git branch -a
* master
1.x
2.x
tags/1.0.0
tags/1.0.1
tags/1.0.2
tags/1.1.0
tags/2.0.0
trunk
$ git tag -l
[ empty ]
and after svn2git is done with your project, you'll get this instead:
$ git branch
* master
1.x
2.x
$ git tag -l
1.0.0
1.0.1
1.0.2
1.1.0
2.0.0
finally, it makes sure the HEAD of master is the same as the current trunk of the svn repo. periodt. π
π§ INSTALLATION π§
make sure you have git, git-svn, and ruby installed. svn2git is a ruby wrapper around git's native SVN support through git-svn. it is possible to have git installed without git-svn installed, so please do verify that you can run $ git svn successfully β like actually run it, don't just assume π
for a Debian-based system, the installation of the prerequisites would look like:
$ sudo apt-get install git-core git-svn ruby rubygems
once you have the necessary software on your system, you can install svn2git through rubygems, which will add the svn2git command to your PATH.
$ sudo gem install svn2git
slay. you're installed. π
β USAGE β
there are several ways you can create a git repo from an existing svn repo. the differentiating factor is the svn repo layout. below is an enumerated listing of the varying supported layouts and the proper way to create a git repo from a svn repo in the specified layout. (enumerated. she's organized.)
- the svn repo is in the standard layout of (trunk, branches, tags) at the root level of the repo.
$ svn2git http://svn.example.com/path/to/repo
- the svn repo is NOT in standard layout and has only a trunk and tags at the root level of the repo.
$ svn2git http://svn.example.com/path/to/repo --trunk dev \
--tags rel --nobranches
- the svn repo is NOT in standard layout and has only a trunk at the root level of the repo.
$ svn2git http://svn.example.com/path/to/repo --trunk trunk \
--nobranches --notags
- the svn repo is NOT in standard layout and has no trunk, branches, or tags at the root level of the repo. Instead the root level of the repo is equivalent to the trunk and there are no tags or branches.
$ svn2git http://svn.example.com/path/to/repo --rootistrunk
- the svn repo is in the standard layout but you want to exclude the massive
docdirectory and the backup files you once accidentally added.
$ svn2git http://svn.example.com/path/to/repo --exclude doc \
--exclude '.*~$'
- the svn repo actually tracks several projects and you only want to migrate one of them.
$ svn2git http://svn.example.com/path/to/repo/nested_project \
--no-minimize-url
if the svn repo is password protected.
$ svn2git http://svn.example.com/path/to/repo \
--username <<user_with_perms>>
you need to migrate starting at a specific svn revision number.
$ svn2git http://svn.example.com/path/to/repo \
--revision <<starting_revision_number>>
you need to migrate starting at a specific svn revision number, ending at a specific revision number.
$ svn2git http://svn.example.com/path/to/repo --revision \
<<starting_revision_number>>:<<ending_revision_number>>
include metadata (git-svn-id) in git logs.
$ svn2git http://svn.example.com/path/to/repo --metadata
the above will create a git repository in the current directory with the git version of the svn repository. hence, you need to make a directory that you want your new git repo to exist in, change into it and then run one of the above commands. note that in the above cases the trunk, branches, tags options are simply folder names relative to the provided repo path. for example if you specified trunk=foo branches=bar and tags=foobar it would be referencing http://svn.example.com/path/to/repo/foo as your trunk, and so on. however, in case 4 it references the root of the repo as trunk. π«Ά
as of svn2git 2.0 there is a new feature to pull in the latest changes from SVN into your git repository created with svn2git. this is a one way sync, but allows you to use svn2git as a mirroring tool for your SVN repositories.
the command to call is:
$ cd <EXISTING_REPO> && svn2git --rebase
π¦ AUTHORS π¦
to convert all your svn authors to git format, create a file somewhere on your system with the list of conversions to make, one per line, for example:
jcoglan = James Coglan <jcoglan@never-you-mind.com>
stnick = Santa Claus <nicholas@lapland.com>
then pass an authors option to svn2git pointing to your file:
$ svn2git http://svn.example.com/path/to/repo \
--authors ~/authors.txt
alternatively, you can place the authors file into ~/.svn2git/authors and svn2git will load it out of there. this allows you to build up one authors file for all your projects and have it loaded for each repository that you migrate. one file to rule them all, main character energy π
if you need a jump start on figuring out what users made changes in your svn repositories the following command sequence might help. it grabs all the logs from the svn repository, pulls out all the names from the commits, sorts them, and then reduces the list to only unique names. so, in the end it outputs a list of usernames of the people that made commits to the svn repository which name on its own line. this would allow you to easily redirect the output of this command sequence to ~/.svn2git/authors and have a very good starting point for your mapping.
$ svn log --quiet | grep -E "r[0-9]+ | .+ |" \
| cut -d'|' -f2 | sed 's/^ //' | sort | uniq
or, for a remote URL:
$ svn log --quiet http://path/to/root/of/project \
| grep -E "r[0-9]+ | .+ |" | cut -d'|' -f2 \
| sed 's/^ //' | sort | uniq
π DEBUGGING π
if you're having problems with converting your repository and you're not sure why, try turning on verbose logging. this will print out more information from the underlying git-svn process. she will tell you things. π£οΈ
you can turn on verbose logging with the -v or --verbose flags, like so:
$ svn2git http://svn.yoursite.com/path/to/repo --verbose
heads up bestie: that's where this part stops! part 2 is coming, don't go anywhere π
β¨ FAQ β¨
ok bestie this is the part where everyone slides into the replies with the same two questions π¬ so let's just get into it, no gatekeeping fr fr π«Ά
- why don't the tags show up in the master branch?? π
The tags won't show up in the master branch because the tags are actually tied to the commits that were created in svn when the user made the tag. Those commits are the first (head) commit of branch in svn that is associated with that tag. So they live over there, not on master, and that's just the way the mapping works, no cap.
If you want to see all the branches and tags and their relationships in gitk you can run the following:
gitk --all
For further details please refer to FAQ #2 (it's right below bestie, we love a sequel π ).
- why don't you reference the parent of the tag commits instead?? π€
Okay so here's the tea π΅ β in svn you are forced to create what are known in git as annotated tags. And it just so happens that svn annotated tags allow you to commit change sets along with the tagging action. Which means the svn annotated tag is a bit more complex than just an annotated tag β it is a commit which is treated as an annotated tag π
Hence, for there to be a true 1-to-1 mapping between git and svn we have to transfer over the svn commit which acts as an annotated tag and then tag that commit in git using an annotated tag. Periodt.
And if we were to reference the parent of this svn tagged commit, there could potentially be situations where a developer would checkout a tag in git and the resulting code base would be different than if they checked out that very same tag in the original svn repo π³. This is only due to the fact that the svn tags allow changesets in them, making them not just annotated tags.
so yeah, that's why we don't do it β it would break the whole "same tag, same code" promise and we are not about that life π
and that's the whole page bestie, you made it to the end, so proud of you π this little legend comes from svn2git 2.3.2, dated 08/04/2016, and it lives in section SVN2GIT(1) of the manual. go forth and migrate your repos, you absolute icon π¦β¨π
π¦ where this page comes from
- debian bookworm: svn2git 2.4.0-3 Β· MIT
- debian trixie: svn2git 2.4.0-3.1 Β· MIT
- ubuntu jammy: svn2git 2.4.0-3 Β· MIT
- ubuntu noble: svn2git 2.4.0-3 Β· MIT
- ubuntu noble: svn2git 2.4.0-3ubuntu0.1 Β· MIT
- ubuntu resolute: svn2git 2.4.0-3.1 Β· MIT
- ubuntu stonking: svn2git 2.4.0-3.1 Β· MIT
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms