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:mergeinfodoes not preserve perfectly. - Empty directories - SVN tracks them, Git does not. Add a
.gitkeepif 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.