开发者

What is the correct way to convert SVN remote branches and tags into local Git branches/tags during SVN to Git migration

开发者 https://www.devze.com 2023-01-06 16:37 出处:网络
What is the correct way to make the remote branches/tags that exist after a git-svn init/git-svn fetch into local Git branches/tags before pushing to my remote Git repo and abandoning SVN altogether.

What is the correct way to make the remote branches/tags that exist after a git-svn init/git-svn fetch into local Git branches/tags before pushing to my remote Git repo and abandoning SVN altogether.

I have:

  • Run git svn init
  • U开发者_运维百科pdated the svn-remote "svn" section of my .git/config file to the following:

    url = file:///Users/Developers/git_transition/svn_repo
    fetch = cascade/trunk:refs/remotes/svn/trunk
    branches = cascade/branches/{5.0GA_CLEANUP,drag-n-drop-def-builder,help-text,hib-annotations,hibernate-annotations,image-editor,ldapconfig,liquibase,move-rename-prototype,progress-bar,progress-bar2,quartz-upgrade,recyclebin,rendering_metrics,shuttle_upgrade,spring3,web-services-no-nuller}:refs/remotes/svn/*
    branches = cascade/branches/{6.x,5.x,4.x,3.x,archive}/*:refs/remotes/svn/*
    tags = cascade/tags/{3.7.x,4.x,5.x,6.x,old-releases}/*:refs/remotes/svn/tags/*
    
  • Run git svn fetch

Does git-svn clone do something beyond init/fetch that turns these branches/tags into local ones?

I tried the advice on Pro Git but there was nothing in the .git/refs/remotes/svn/ directory except the empty 6.x, 5.x, 4.x, 3.x, tags, and archive directories. I did verify that the remote branches are there with git branch -r.

Someone suggested that I needed to systematically checkout all of the remote branches as local ones: git checkout -b <local_branch_name> <svn_remote_branch_name> but I haven't gotten a definitive answer anywhere.

I have been able to conver the tags by using this script:

git for-each-ref --format="%(refname)" refs/remotes/svn/tags/6.x |
grep -v @ | while read tag; do GIT_COMMITTER_DATE="$(git log -1
--pretty=format:"%ad" "$tag")" GIT_COMMITTER_EMAIL="$(git log -1
--pretty=format:"%ce" "$tag")" GIT_COMMITTER_NAME="$(git log -1
--pretty=format:"%cn" "$tag")" git tag -m "$(git log -1
--pretty=format:"%s%n%b" "$tag")" ${tag#refs/remotes/svn/tags/6.x/}
"$tag"; done

for each of the tags folders.


For a one-shot operation like this, before leaving behind a SVN repo, I like to clone it using the ruby script svn2git

=== Examples

Say I have this code in svn:

  trunk
    ...
  branches
    1.x
    2.x
  tags
    1.0.0
    1.0.1
    1.0.2
    1.1.0
    2.0.0

git-svn will go through the commit history to build a new git repo.
It will import all branches and tags as remote svn branches, whereas what you really want is git-native local branches and git tag objects.
So after importing this project I'll get:

  $ git branch
  * master
  $ git branch -a
  * master
    1.x
    2.x
    tags/1.0.0
    tags/1.0.1
    tags/1.0.2
    tags/1.1.0
    tags/2.0.0
    trunk
  $ git tag -l
  [ empty ]

After svn2git is done with your project, you'll get this instead:

  $ git branch
  * master
    1.x
    2.x
  $ git tag -l
    1.0.0
    1.0.1
    1.0.2
    1.1.0
    2.0.0


According to an answer on Git mailing list, I don't need to convert these branches into local ones before pushing them to my remote repo. I just need to do:

git push <remote_git_repo_name> svn/<branch-name>:refs/heads/<branch-name>


To do exactly that you want just use SubGit project. You can install it into your SVN repository. So that a linked Git repository is created (with SVN tags translated to Git tags, svn:ignores to .gitignore and so on). That Git repository is kept in sync with the SVN repository: when you push to a Git repository, this changes is translated to the SVN repository, and vice versa.

If you need client-only solution, I would recommend you to use SmartGit. It also preserves SVN concepts in Git repository.

And what I wouldn't recommend you to use it git-svn.


There is no easy/straightforward way to convert SVN tag-branches to native git tags after git svn conversion. There are number of scripts out there to convert SVN tags but most of them merely tag-&-remove corresponding branches outside of "master" branch so new tags won't show up in commits history even if "master" have commits identical to the tagged ones.

In order to solve this problem I ended up writing my own utility "git-svn-convert-tags" which finds and tags commits identical to SVN "tags" within "master" branch. The logic is simple: utility compares all commits in current branch (e.g. "master") to tag-branches' HEADs. When binary-identical commit is found new tag is assigned and SVN tag-branch is deleted. Using this approach I've managed to successfully convert tags in many git-svn imported repositories to perfect git tag layout.


This is a example on how to convert one of these branch references to a tag:

# rename the branch reference
git branch -t rel_20101019 remotes/svn/tags/rel_20101019

# checkout the branch
git checkout rel_20101019

# create the tag for it
git tag rel_20101019

# go back to master
git checkout master

# delete the branch
git branch rel_20101019 –d

# now you can push your branch and tag changes to your origin
git push origin –all
git push origin –tags
0

精彩评论

暂无评论...
验证码 换一张
取 消