Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
136 views
in Technique[技术] by (71.8m points)

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.

question from:https://stackoverflow.com/questions/66050729/migrating-svn-project-to-git-branches-and-tags-coming-out-completely-wrong

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I have to admit that your migration method is pretty good overall.

But this git-config section is immediately dubious to me:

branches = Branches/35/*:refs/remotes/*
branches = Branches/36/*:refs/remotes/*
branches = Branches/37/*:refs/remotes/*
# ...
tags = Tags/35/*:refs/remotes/tags/*
tags = Tags/36/*:refs/remotes/tags/*
tags = Tags/37/*:refs/remotes/tags/*
# ...

Assuming you've got an svn tree somewhat similar to this:

https://my/svn/project/
├── Branches
│?? ├── 35
│?? │?? ├── Buzqx
│?? │?? └── Fubar
│?? ├── 36
│?? │?? ├── Buzqx
│?? │?? └── Fubar
│?? └── 37
│??     ├── Buzqx
│??     └── Fubar
...

... the above git-config asks to map:

  • Branches/35/Fubar to refs/remotes/Fubar,
  • Branches/35/Buzqx to refs/remotes/Buzqx,
  • Branches/36/Fubar to refs/remotes/Fubar,
  • Branches/36/Buzqx to refs/remotes/Buzqx,
  • Branches/37/Fubar to refs/remotes/Fubar,
  • Branches/37/Buzqx to refs/remotes/Buzqx,
  • etc (tags similarly).

Which I hope you can see cannot end well. The result you get is exactly what you asked for :)

Try redoing the branch/tag mapping so that there's no namespace clashing.

Also see the last paragraph of CAVEATS in man git-svn:

When using multiple --branches or --tags, git svn does not automatically handle name collisions (for example, if two branches from different paths have the same name, or if a branch and a tag have the same name). In these cases, use init to set up your Git repository then, before your first fetch, edit the $GIT_DIR/config file so that the branches and tags are associated with different name spaces. For example:

branches = stable/*:refs/remotes/svn/stable/*
branches = debug/*:refs/remotes/svn/debug/*

EDIT: mapping example for tags

Each tag folder has a sub-folder for the releases e.g. 47/47.0, 47/47.1

This would be correctly described by tags lines in your initial git-config, but let me just tweak it a little bit, so maybe you can better see what's going on. Suppose you use this instead:

tags = Tags/35/*:refs/remotes/svn-tag-*
tags = Tags/36/*:refs/remotes/svn-tag-*
tags = Tags/37/*:refs/remotes/svn-tag-*
# ...
tags = Tags/49/*:refs/remotes/svn-tag-*

Then, this would map SVN Tags/47/47.1 to Git branch1 named svn-tag-47.1.
Of course, this'd map SVN Tags/35/35.0 to Git branch named svn-tag-35.0 too, etc.

Now, notice: your /Branches structure is different from /Tags (there're no per-version subdirs!..) But your git-config mappings are the same. That's why you get issues.

Try something like this instead:

branches = Branches/49:refs/remotes/latest
branches = Branches/48:refs/remotes/stable
branches = Branches/47:refs/remotes/lastyear-stable
# ...
branches = Branches/35:refs/remotes/pre-eol

#-- or at the very very least (NOT RECOMMENDED):
#branches = Branches/*:refs/remotes/svn-branch-*

1 svn tags must be branches in git, because they aren't immutable like git tags are.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...