2017年1月15日日曜日

Migrate svn repository to git remote bare repository

移行対象となるSVNのリポジトリのフォルダ構成は以下の通り。
この内、srcとtestのみを移行対象としたい(他は必要に応じて別プロジェクトとして移行する)。

http://192.168.XXX.XXX/svn/projectA/
trunk/src/*
trunk/test/*
trunk/env/*
trunk/doc/*
・・・
branches/branchXXX/src/*
branches/branchXXX/test/*
branches/branchXXX/env/*
branches/branchXXX/doc/*
・・・
tags/tagXXX/src/*
tags/tagXXX/test/*
tags/tagXXX/env/*
tags/tagXXX/doc/*


予めSVNのコミット履歴からユーザー情報を抽出し、メールアドレスを補完したものを作成しておく。

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


# operation on server(for remote bare repository)
cd /var/git/repositories

# create bare repository
git init --bare --shared=true ./projectA.git

# convert svn remote repository(only src and test directory) to git local repository with git-svn
git svn init -s --ignore-paths='^branches/.+/(?!src|test)|^tags/.+/(?!src|test)|^trunk/(?!src|test)' http://192.168.XXX.XXX/svn/projectA ./temp.git

# if necessary, modify ".git/config" to select brances and tags for migration.
# (ex)
# branches/{branch1,branch2,branch4}:refs/remotes/*
# tags = tags/{tag1,tag2,tag4}:refs/remotes/tags/*
vi .git/config

cd ./temp.git

# git can not deal empty directory, so create .gitkeep file(0 byte) into each empty directories.
# need to correct Fetcher.pm (change die "Failed to strip path... to print "Failed to strip path...)
# see http://stackoverflow.com/questions/35786548/git-svn-clone-fails-with-failed-to-strip-path
sudo vi /usr/share/perl5/Git/SVN/Fetcher.pm
git config svn-remote.svn.preserve-empty-dirs "true" 
git config svn-remote.svn.placeholder-filename ".gitkeep" 

# start conversion from svn to git with authors-transform.txt(prepaired above)
# XXX is HEAD revision number on svn repository.
git svn fetch -r 1:XXX -A authors-transform.txt 2>&1 | tee fetch_result.log

# take long time...

# push local git repository(generated by git-svn) to remote bare repository
git remote add bare /var/git/repositories/projectA.git
git config remote.bare.push 'refs/remotes/*:refs/heads/*'
git push bare

# change branch name(trunk => master)
cd /var/git/repositories/projectA.git
git branch -m trunk master

# clean up tags because git-svn converts svn-tags to git-branches
./clean_up_tags.sh


# clean_up_tags.sh
git for-each-ref --format='%(refname)' refs/heads/tags |
cut -d / -f 4 |
while read ref
do
  git tag "$ref" "refs/heads/tags/$ref";
  git branch -D "tags/$ref";
done

> git svn fetch -r 1:XXX
git svn fetchでHEADを指定すると
fatal: refs/remotes/trunk: not a valid SHA1
update-ref refs/heads/master refs/remotes/trunk: command returned error: 128
のようなエラーでfetchが失敗するため、リビジョン番号を直接指定する。
また、リビジョン番号1からのコミットを移行対象として記載したが、
自分の場合はSVNで構成管理を始めた当初、レイアウトが標準(trunk,branches/tags)になっておらず、
fetchでエラーが多発したため、標準レイアウトでコミットし始めた頃のリビジョンからを移行対象とした。

0 件のコメント:

コメントを投稿