LoginSignup
1
5

More than 3 years have passed since last update.

いまさらだけどSubversionからGitへ移行する(その1: リポジトリー変換)

Last updated at Posted at 2020-07-12

目的

Trac+Subversion, Redmine+Subversion/Git, GitLab CE などを時代に合わせてオンプレで運用してきたが、サーバーの管理・維持などの関係もあり、Trac+Subversion は廃止し、GitLab あるいは Redmine+Git に移行したくなってきた。

ところで、10年以上前に、CVS で運用していたリポジトリーを cvs2svn1 により SVN に移行したことがあるが、この記事を書くのにGitHubに移行されたものを見ると、SVN だけでなく Git/Mercurial/Bazaar にも移行できるっぽい。VSS=Microsoft Visual SourceSafeで運用していたリポジトリーは闇に葬った…。(余談)

参考

基本的に Pro Git book の手順や上記 Qiita 記事やブログ記事などで見つかるもので良いと思うのだが…

実際の移行とハマったところなどを記載していく。

SVNディレクトリー構成

いわゆるtrunk,branches,tagsのスタンダードレイアウト。基本的にこれで運用していたので良かった。もちろんプロジェクト毎に別のSVNリポジトリーとして分離していた。

たとえば、 Apache Software Foundationの様に全社のプロジェクトが同一SVNリポジトリーにフラットにぶら下がっている様なものや、trunk,branches,tagsを使わない独自形式だと、git svnのオプション指定も異なってくるはず。

環境

あんまり関係なさそうだけど一応。

  • 移行元: Subversion
    • CentOS 7 + Subversion 1.7.14 (r1542130) (標準 RPM package)
  • 移行作業: git-svn
    • macOS 10.15.5 + git-svn 2.27.0 (svn 1.10.4) (brew版 git)
  • 移行先: Git
    • CentOS7 + GitLab CE 13.1.4 (Omnibus package版)

移行手順

生SVNリポジトリーの入手

外部のSVNホスティングサービス利用ならまだしも、自分がSVNサーバー管理者だっり、他のSVN管理者でもgit-svnで移行するということならその管理者の協力が得られるはずなので、生のSVNリポジトリーをローカルにコピーして作業するのが良いと思われる。

Pro Git Bookや各種記事には次のようなコマンド例があり(時代的に2016に終了した、Google Code2のSVNからの移行でしょうか?)

$ git svn clone http://my-project.googlecode.com/svn/ \
      --authors-file=users.txt --no-metadata -s my_project

この、http(WebDAV)のリモートからの取得で失敗することが多いので、git svn init してから git svn fetch し、失敗した場合そのリビジョンから git svn fetch -r1234:HEAD にて再開するという記事が多いですが、生のリポジトリーが入手できるなら、ローカルで完結させたほうが絶対楽です。いまだにcommitされ生きているSVNリポジトリーならこの限りではないですが…結局どこかのタイミングで運用停止して変換するでしょうし…

以下、/var/lib/svn/myproj にSVNプロジェクトがあるものとして話をすすめます。

authors 一覧ファイルを作る

ここは基本的に Pro Git Book の通りです。

SVN は http などの認証ユーザー名が Author になるが、Git の場合は、 user.nameuser.email が Author になるのでその変換テーブルが必要。

いや、cvs2svn なんかで変換した年代物のリポジトリーなんて、遠い昔にそんなヤツいた?ってのをみんなに聞いたり、誰かを辿るのにすごく時間がかかる面倒くさい作業。まあ、わからなければ適当な名前とメールアドレスを入れちゃえばよいのですが…。

チェックアウト

$ svn checkout file:///var/lib/svn/myproj myproj-svn

抽出

$ cd myproj-svn
$ svn log --xml | grep author | sort -u | \
  perl -pe 's/.*>(.*?)<.*/$1 = /' > /tmp/myproj-authors.txt
username1 =
username2 =
.
.

というファイルができるので

username1 = Taro Yamada <taro@example.com>
username2 = Hanako Toire <hanako@example.com>
.
.

svn checkout したワーキングコピーはAuthor一覧を抽出するだけなのでここで消しても良い。

実際の移行

いろいろなところに書かれている事例の通り、自分もhttps://でやったことがあるがリビジョン数やタグ・ブランチの少ないテスト用のリポジトリーでは成功するが、実運用しているリポジトリーに関しては何度も失敗しました。前に書いたとおり、ローカルに持ってきて、file:///でやるとネットワークの影響がなく成功しているのか?しかし、ローカルでもとても時間がかかります。

$ git svn init file:///var/lib/svn/myproj/ --no-metadata -s myproj
$ cd myproj
$ git svn fetch --authors-file=/tmp/myproj-authors.txt

--no-metadata はcommit logにgit-svn-idを付与しないためにつけています。そもそも、file:///var/lib/svn/myproj/とローカルのリポジトリを指定しているのでgit-svn-idにローカル情報が見えてかっこ悪くなるし、そもそもGit移行後は不要な情報と自分は判断しました。

タグとブランチの変換

Pro Git bookでは、

タグを Git のタグとして扱うには、次のコマンドを実行します。
次に、refs/remotes 以下にあるそれ以外の参照をローカルブランチに移動します。

と言うところの方法として、.git/ディレクトリの中をcp,rmにて操作しているが、自分の環境ではこれで失敗しました(24時間以上変換にかかったGitリポジトリーをバックアップ取らずに台無しに…)。ちょっと情報元のスニペットのリンクは失念したけど、参考として載せたgit-svnでSVN→Gitへの移行をやってみたログの次の方法で成功しました。

ブランチ

$ for BRANCH_NAME in $(git branch -r | grep -ve 'origin/tags\|origin/trunk\|.*@\d*' | sed -e 's:origin/::'); do
    git checkout -b "$BRANCH_NAME" "origin/$BRANCH_NAME"
done;
$ git checkout master

タグ

$ for TAG_NAME in $(git branch -r | grep -e 'origin/tags' | grep -ve '.*@\d*' | sed -e 's:origin/tags/::'); do
  git tag "$TAG_NAME" "origin/tags/$TAG_NAME"
done

リモートリポジトリーへのpush

こちらは、普通の方法。GitLabにpushしたが何でも良いかと。

$ git remote add origin git@gitlab.example.com:mygroup/myproj.git
$ git push -u origin --all
$ git push -u origin --tags

つづく

SVNのリポジトリー形式により、変換したGitリポジトリーを更に変換操作した場合もあったので、その点を書くかも。→ いまさらだけどSubversionからGitへ移行する(その2)


  1. 2020-07-01に閉鎖につきWebArchiveのリンク 

  2. Bidding farewell to Google Code 

1
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
5