By admin , 29 April 2026

What you will achieve

You will convert an SVN repository to Git, preserving authors, dates, branches, and tags, and push the result to a Git host. The conversion typically takes 30 minutes for medium repositories and a few hours for large ones.

Step 1: prepare

Audit the SVN repo:

svn info https://svn.example.com/repo
svn ls https://svn.example.com/repo
# Confirm: trunk, branches, tags layout?

Step 2: build authors mapping

SVN authors are usernames; Git wants Name <email>:

svn log --xml https://svn.example.com/repo \
  | grep -E '<author>' \
  | sort -u \
  | sed -E 's/.*>(.+)<.*/\1 = \1 <\[email protected]>/' \
  > authors.txt

Edit authors.txt by hand to put real names and emails:

jdoe = Jane Doe <[email protected]>
bsmith = Bob Smith <[email protected]>

Step 3: convert with git svn

git svn clone \
    --stdlayout \
    --authors-file=authors.txt \
    https://svn.example.com/repo \
    repo.git
cd repo.git

--stdlayout assumes the standard trunk/, branches/, tags/ layout. For non-standard, use --trunk, --branches, --tags explicitly.

Conversion may take an hour for large repos. The process replays every SVN revision into a Git commit.

Step 4: convert SVN tags to Git tags

SVN "tags" are branches in Git's view post-conversion. Convert them:

git for-each-ref refs/remotes/origin/tags --format='%(refname:short)' \
  | while read ref; do
    tag="${ref#origin/tags/}"
    git tag "$tag" "$ref"
    git update-ref -d "refs/remotes/$ref"
  done

Step 5: convert SVN branches to Git branches

git for-each-ref refs/remotes/origin --format='%(refname:short)' \
  | grep -v '^origin/tags' \
  | while read ref; do
    branch="${ref#origin/}"
    if [ "$branch" != "trunk" ]; then
      git branch "$branch" "$ref"
    fi
    git update-ref -d "refs/remotes/$ref"
  done

Step 6: rename trunk to main

git branch -m trunk main

Step 7: verify

git log --oneline | wc -l
svn log -q https://svn.example.com/repo | grep -c '^r'
# Counts should be in the same ballpark
git tag | wc -l
git branch | wc -l

Spot check a representative commit:

git log -1 --format='%an %ae %s' <sha>
svn log -r <rev> https://svn.example.com/repo

Step 8: push to a Git host

git remote add origin [email protected]:myorg/repo.git
git push -u origin --all
git push origin --tags

Step 9: handle externals

SVN externals do not translate. Decide:

  • Vendor in - copy external content into the repo.
  • Submodules - make each external a Git submodule.
  • Package manager - use npm/pip/cargo for what should be dependencies.

Step 10: handle large or binary content

If the SVN repo carried large binaries:

git filter-repo --strip-blobs-bigger-than 50M
# or migrate them to LFS
git lfs migrate import --include="*.psd,*.zip" --everything

Step 11: communicate the cutover

  • Announce the cutover date.
  • Make SVN read-only after the cutover.
  • Provide instructions for cloning the new Git repo.
  • Schedule training - the SVN-to-Git mental shift is real.

Step 12: keep SVN read-only

For audit and lookup. Do not delete - someone will need it.

Common pitfalls

  • Incomplete authors file - empty author entries break commits.
  • Non-standard layout - use explicit --trunk, etc.
  • SVN merge tracking - svn:mergeinfo does not preserve perfectly.
  • Empty directories - SVN tracks them, Git does not. Add a .gitkeep if needed.

Alternative: svn2git

# Ruby tool wrapping git svn
sudo apt install svn2git
svn2git https://svn.example.com/repo --authors authors.txt

Cleaner output for the standard layout case.

The result

A Git repository with the SVN history preserved, ready for modern workflows. The migration is mechanical; the cultural transition (training, branching habits) is the real work.