Skip to content

Latest commit

 

History

History
178 lines (147 loc) · 10.9 KB

import-svn.asc

File metadata and controls

178 lines (147 loc) · 10.9 KB

Subversion

先ほどの節で 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 タグを除去します。 (ちょっと見ればわかりますが、これは grepsort、そして perl といったコマンドが使える環境でないと動きません) この出力を users.txt にリダイレクトし、そこに Git のユーザーデータを書き足していきます。

このファイルを git svn に渡せば、作者のデータをより正確にマッピングできるようになります。また、Subversion が通常インポートするメタデータを含めないよう git svn に指示することもできます。そのためには --no-metadataclone コマンドあるいは 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 サーバーにきれいにインポートできました。