Search code examples
gitsvngit-svn

Migrating SVN project to Git - Branches and Tags coming out completely wrong


My aim is to migrate my SVN stored project to Git in a one-way, one-shot migration, i.e. once it's done we use Git and dump SVN completely. To that end I'm trying to migrate the commit logs from v35.0 to latest (currently v49.0) of the application. The solution for application consists of about 20-30 projects, libraries, exes, etc...

The structure (and case) of my project in SVN is as follows:

  • Branches
    • 35
    • ...
    • 49
  • Tags
    • 35
      • 35.0
    • ...
    • 47
      • 47.0
      • 47.1
  • Trunk

There are other folders at the same level as Branches/Tags/Trunk, e.g. FeatureBranches, but they can all be ignored.

I run the following in my SVN trunk folder to get authors formatted correctly for Git:

svn log -q | awk -F '|' '/^r/ {sub("^ ", "", $2); sub(" $", "", $2); print $2" = "$2" <"$2">"}' | sort -u > authors-transform.txt

I run the following command in Git Bash prompt in a new empty folder I created for the migration:

git svn init --prefix "" --no-metadata --trunk=Trunk --branches=Branches --tags=Tags https://my/svn/project/

[UPDATED 08/02] Then I edit the /.git/config file and remove branches line and replace the tags line with:

tags = Tags/35/*:refs/remotes/tags/*
tags = Tags/36/*:refs/remotes/tags/*
tags = Tags/37/*:refs/remotes/tags/*
tags = Tags/38/*:refs/remotes/tags/*
tags = Tags/39/*:refs/remotes/tags/*
tags = Tags/40/*:refs/remotes/tags/*
tags = Tags/41/*:refs/remotes/tags/*
tags = Tags/42/*:refs/remotes/tags/*
tags = Tags/43/*:refs/remotes/tags/*
tags = Tags/44/*:refs/remotes/tags/*
tags = Tags/45/*:refs/remotes/tags/*
tags = Tags/45/*:refs/remotes/tags/*
tags = Tags/46/*:refs/remotes/tags/*
tags = Tags/47/*:refs/remotes/tags/*
tags = Tags/48/*:refs/remotes/tags/*
tags = Tags/49/*:refs/remotes/tags/*

I then run the command:

git lfs install

I then copy into the folder a .gitattributes file containing the list of files to be tracked be Git LFS. I've made multiple attempts at this so I saved this file from a previous attempt. I'd used git lfs track commands previously. Similarly I copy in a .gitignore file and the authors-transform.txt file created by the earlier command.

Next I run:

git svn fetch --log-window-size=5000 -A authors-transform.txt

Then I go away for around 25 hours that it roughly takes and do something else, eat, sleep, more work etc..

I then run:

for t in $(git for-each-ref --format='%(refname:short)' refs/remotes/tags); do git tag ${t/tags\//} $t && git branch -D -r $t; done
for b in $(git for-each-ref --format='%(refname:short)' refs/remotes); do git branch $b refs/remotes/$b && git branch -D -r $b; done
for p in $(git for-each-ref --format='%(refname:short)' | grep @); do git branch -D $p; done
git branch -d trunk

The final command above resulted in:

fatal: Couldn't look up commit object for HEAD

[UPDATED 08/02] I fire up SourceTree and point it at my folder and the horror unfolds. There is 1 branch called "trunk" and there are 50 tags. Only 1 of hte tags is correct - 35.0, the rest are all named after one of the solution project folders; some are almost identical except there is an @number after them, i.e. Fubar@1423, Fubar@1568

If this hadn't of all gone horribly wrong I would have run the following to complete:

$ git remote add origin <AzureDevOps git url>
$ git push origin --all
$ git push origin --tags

I'm a relative Git noob and so have been piecing things together from other colleagues and Git docs but I have to admit I have a big case of imposter syndrome and am totally lost at this point. If anybody has any ideas for commands or config I got wrong and what I should do to achieve my aim I would be most appreciative.


Solution

  • So it turns out typos + jumping the gun were my enemy.

    In my list of tags I had repeated the following line twice:

    tags = Tags/45/*:refs/remotes/tags/*
    

    After that I had the following line before the tag had been created in SVN:

    tags = Tags/45/*:refs/remotes/tags/*
    

    In order to make the tags for example, 47.0 and 47.1 appear under a collapsible 47 tag in my Git UI (SourceTree) I updated the above lines used in the config:

    tags = Tags/47/*:refs/remotes/tags/47/*
    

    The above combined with the removal of the branch lines mentioned in edit on the main question got me 90% of the way there. I ended up with a main and a tags from 35 to 49 (branch/tag where made in SVN by the time I tried again). I still got a bunch of weird tags like 47.1@343, around 150 in fact. However, since it was so close I just deleted those tags getting Git to produce a list of tags to a files and used that as the basis for a batch file that contained a bunch of "git tag -d " commands.