先ほどの節で git svn
の使い方を読んでいれば、話は簡単です。まず git svn clone
でリポジトリを作り、そして Subversion サーバーを使うのをやめ、新しい Git サーバーにプッシュし、あとはそれを使い始めればいいのです。これまでの歴史が欲しいのなら、それも Subversion サーバーからプルすることができます (多少時間がかかります)。
しかし、インポートは完全ではありません。また時間もかかるので、正しくやるのがいいでしょう。まず最初に問題になるのが作者 (author) の情報です。Subversion ではコミットした人すべてがシステム上にユーザーを持っており、それがコミット情報として記録されます。たとえば先ほどの節のサンプルで言うと schacon
がそれで、blame
の出力や git svn log
の出力に含まれています。これをうまく Git の作者データとしてマップするには、Subversion のユーザーと Git の作者のマッピングが必要です。users.txt
という名前のファイルを作り、このような書式でマッピングを記述します。
schacon = Scott Chacon <[email protected]>
selse = Someo Nelse <[email protected]>
SVN で使っている作者の一覧を取得するには、このようにします。
$ svn log --xml | grep author | sort -u | \
perl -pe 's/.*>(.*?)<.*/$1 = /'
これは、まずログを XML フォーマットで生成します。その中から作者の情報を含む行だけを抽出し、重複を削除して、XML タグを除去します。
(ちょっと見ればわかりますが、これは grep
や sort
、そして perl
といったコマンドが使える環境でないと動きません)
この出力を users.txt
にリダイレクトし、そこに Git のユーザーデータを書き足していきます。
このファイルを git svn
に渡せば、作者のデータをより正確にマッピングできるようになります。また、Subversion が通常インポートするメタデータを含めないよう git svn
に指示することもできます。そのためには --no-metadata
を clone
コマンドあるいは init
コマンドに渡します。そうすると、 import
コマンドは次のようになります。
$ git svn clone http://my-project.googlecode.com/svn/ \
--authors-file=users.txt --no-metadata -s my_project
これで、Subversion をちょっとマシにインポートした my_project
ディレクトリができあがりました。コミットがこんなふうに記録されるのではなく、
commit 37efa680e8473b615de980fa935944215428a35a
Author: schacon <schacon@4c93b258-373f-11de-be05-5f7a86268029>
Date: Sun May 3 00:12:22 2009 +0000
fixed install - go to trunk
git-svn-id: https://my-project.googlecode.com/svn/trunk@94 4c93b258-373f-11de-
be05-5f7a86268029
次のように記録されています。
commit 03a8785f44c8ea5cdb0e8834b7c8e6c469be2ff2
Author: Scott Chacon <[email protected]>
Date: Sun May 3 00:12:22 2009 +0000
fixed install - go to trunk
Author フィールドの見た目がずっとよくなっただけではなく、git-svn-id
もなくなっています。
インポートした後には、ちょっとした後始末も行ったほうがよいでしょう。
たとえば、git svn
が作成した変な参照は削除しておくべきです。
まずはタグを移動して、奇妙なリモートブランチではなくちゃんとしたタグとして扱えるようにします。そして、残りのブランチを移動してローカルで扱えるようにします。
タグを Git のタグとして扱うには、次のコマンドを実行します。
$ cp -Rf .git/refs/remotes/origin/tags/* .git/refs/tags/
$ rm -Rf .git/refs/remotes/origin/tags
これは、リモートブランチのうち remotes/origin/tags/
で始まる名前のものを、実際の (軽量な) タグに変えます。
次に、refs/remotes
以下にあるそれ以外の参照をローカルブランチに移動します。
$ cp -Rf .git/refs/remotes/origin/* .git/refs/heads/
$ rm -Rf .git/refs/remotes/origin
このとき、Subversionではブランチが1つだったのにもかかわらず、名前が`@xxx`(xxxは数字)で終わる余分なブランチがいくつか出来てしまうことがあります。Subversionの「ペグ・リビジョン」という機能が原因なのですが、Gitにはこれと同等の機能は存在しません。よって、`git svn`コマンドはブランチ名にsvnのバージョン番号をそのまま追加します。svnでペグ・リビジョンをブランチに設定するときとまさに同じやり方です。もうペグ・リビジョンがいらないのであれば、`git branch -d`コマンドで削除してしまいましょう。
インポートが終わり、過去のブランチはGitのブランチへ、過去のタグはGitのタグへと変換できました。
最後に後始末についてです。残念なことに、`git svn`は`trunk`という名前の余計なブランチを生成してしまいます。Subversionにおけるデフォルトブランチではあるのですが、`trunk`の参照が指す場所は`master`と同じです。`master`のほうが用語としてもGitらしいですから、余分なブランチは削除してしまいましょう。
$ git branch -d trunk
これで、今まであった古いブランチはすべて Git のブランチとなり、古いタグもすべて Git のタグになりました。最後に残る作業は、新しい Git サーバーをリモートに追加してプッシュすることです。自分のサーバーをリモートとして追加するには以下のようにします。
$ git remote add origin git@my-git-server:myrepository.git
すべてのブランチやタグを一緒にプッシュするには、このようにします。
$ git push origin --all
$ git push origin --tags
これで、ブランチやタグも含めたすべてを、新しい Git サーバーにきれいにインポートできました。