Migrating Projects from SVN to Git with Full History
Subversion was the backbone of version control for enterprise projects for many years. But the industry has moved on. Git has become the standard, and the demand for migration from SVN to Git keeps growing. This post walks through the steps I followed to move an SVN project to Git without losing history, tags, or branches.
You can read this post in Turkish.
Prerequisites
Three tools are needed for this migration:
- git and git-svn (the bridge between Git and Subversion)
- subversion (SVN client)
- A text editor (vim or nano)
If git-svn is not available on your system, jump to Step 0 below for a Docker-based workaround.
Step 0: Use Docker When git-svn Is Missing
Some systems do not ship git-svn by default. Instead of hunting down packages, you can spin up a container:
docker run -it --network=host ubuntu bashOnce inside the container, install the required packages:
apt update && apt install git git-svn subversion vim -yThe --network=host flag ensures the container can reach your SVN server. After the migration is complete, you can discard the container.
Step 1: Checkout the SVN Repository
Start by checking out the project from SVN. Use a full checkout so all branches and tags are available locally.
svn checkout http://svn-adresi/svn/proje proje-svnReplace the URL with your actual SVN repository address.
Step 2: Extract the List of Committers
Git commits require proper author information (name and email). SVN only stores usernames. You need to extract every unique committer from the SVN log and build a mapping file.
cd proje-svn
svn log -q | awk -F '|' '/^r/ {sub("^ ", "", $2); sub(" $", "", $2); print $2" = "$2" <"$2">"}' | sort -u > users.txt
mv users.txt ../
cd ..This command parses the SVN log and outputs lines in the format:
username = username <username>Step 3: Map SVN Usernames to Git Authors
Edit the users.txt file and replace the placeholder entries with real names and email addresses:
jdoe = John Doe <jdoe@example.com>
asmith = Alice Smith <asmith@example.com>If your SVN server uses a consistent pattern (for example, usernames are also email prefixes), you can automate the mapping:
sed -i 's/>/@example.com>/g' users.txtThis appends @example.com to each username, turning jdoe = jdoe <jdoe> into jdoe = jdoe <jdoe@example.com>. You still need to fill in full names manually.
Step 4: Clone the SVN Repository with git-svn
With the author mapping ready, clone the repository using git svn clone. The --stdlayout flag tells git-svn that the repository follows the standard SVN layout (trunk, branches, tags).
git svn clone http://svn-adresi/svn/proje --authors-file=users.txt --stdlayout --no-metadata --prefix "" proje-gitKey flags explained:
| Flag | Purpose |
|---|---|
--authors-file=users.txt | Map SVN usernames to Git authors |
--stdlayout | Use standard trunk/branches/tags layout |
--no-metadata | Omit SVN metadata from commit messages |
--prefix "" | Keep remote reference names clean |
This step takes time depending on the repository size. Every commit from SVN history is replayed as a Git commit with proper author information.
Step 5: Convert SVN Branches and Tags to Git
After the clone completes, branches and tags are stored as remote references. They need to be converted to native Git objects.
Convert Tags
SVN tags appear under refs/remotes/tags/. Move them to proper Git tags:
for t in $(git for-each-ref --format='%(refname:short)' refs/remotes/tags); do
git tag ${t/tags\//} $t
git branch -D -r $t
doneConvert Branches
Regular branches live under refs/remotes/. Promote them to local branches:
for b in $(git for-each-ref --format='%(refname:short)' refs/remotes); do
git branch $b refs/remotes/$b
git branch -D -r $b
doneClean Up
Some references may contain @ symbols (git-svn artifacts). Remove them:
for p in $(git for-each-ref --format='%(refname:short)' | grep @); do
git branch -D $p
doneThe trunk branch is no longer needed since Git uses main or master as the default branch. Remove it:
git branch -d trunkStep 6: Push to a New Git Remote
The local Git repository is now ready. Add a remote and push everything:
git remote add origin http://git-adresi/yeni/git-projesi.git
git push origin --all
git push origin --tags--all pushes all branches. --tags pushes all tags. The new repository now contains the full history, every branch, and every tag from the original SVN project.
Wrapping Up
Migrating from SVN to Git with full history is a straightforward process when you follow the right steps. The key is preparing the author mapping file correctly and using git-svn with the right flags. Branches and tags need a small conversion step after the clone, but the entire process is scriptable and repeatable.
The Docker workaround solves the environment problem cleanly when git-svn is not available. Once the migration is done, the team can start using Git with all the history intact and no lost context.
Originally published in Turkish on Medium