今更感がぷんぷん漂ってますが、Subversionで管理してる会社のレポジトリを分割しながらGitへ移行させました。
分かってしまえばそんなに面倒でもないんですが、結構ハマったところもあるので誰かの参考になればと思いメモを兼ねてエントリー。

うちの会社は2003年あたりからSubversionでソース管理を始めて、今まででだいたい3200コミットでダンプすると約1.3GB程度のリポジトリになる規模。
でも、丁度10年で3200コミットだから平均するとだいたいコミット/月って感じだし、おまけにダンプしたリポジトリは大きいけど管理してるソースの中身は不要部分のコメントアウトという状態。
早い話があまり重要じゃないうえにデータも汚いんで、本当だったら移行しないで綺麗にしたほうがいいような感じだったり。

おまけに、リポジトリはプロジェクトごとに分かれているわけじゃなく、

trunk
  project1
  project2
  .
  .
  .
  project70
tags
branch

ってな感じで約70程度の大小様々なプロジェクトが1つのリポジトリに並んでる。

そんなこんなリポジトリをプロジェクト単位でGitに移行させようというのが、今回の話。

色々調べてみると、大まかな流れとしては

  1. svndump dump でSubversionのデータをダンプ
  2. 取り出したデータから svndumpfilter でプロジェクト単位に抽出
  3. 抽出したデータを svndump load で新しいリポジトリにロード
  4. git svn clone でローカルのGitリポジトリにSVNでチェックアウト
  5. git push でSubversionから取り出したデータをプッシュ
  6. git [mv|add] コマンドでディレクトリの構造を調整

という感でいけるみたい。1-3はサーバー側で行い、4-6はクライアント側で行う。

で実際に利用したスクリプトは、

サーバー側処理

ローカル側処理

な感じ。サーバーもクライアントもWindowsなのにローカルのスクリプトがBashになってるのは、msysGitを利用してるから。

内容的には以下の感じで少し調整してある。

split_repository.bat

  • 2行目の include には、抽出したいプロジェクト名を指定(いくつでも指定できるみたい)
  • 6行目の mkdir trunk は何故か先に作っておかないとエラーになる

svn2git.sh

  • 2行目の tr コマンドは、GitLabでHTTP経由のリポジトリがすべて小文字になることへの対応
  • 3行目の --no-metadata を指定しないとSVNとの紐付けが残ってしまう
  • 最終的には7,8行目でディレクトリ構造を調製するが、先に6行目で push しておかないと弾かれる

あとは、スクリプトには出てこないけど、実際に動かすと以下の点が引っかかった。

ダンプの際に

svndumpfilter: Invalid copy source path '/path/project'

が出てくるときは、includeに「 path/project 」を追加すればOK。

インポートの時に

* adding path : path/project ...svnadmin: File not found: transaction '6-6', path 'path/project'

が出てくるときは、インポート先のレポジトリに「 svn mkdir path 」でディレクトリを作ればOK。

GitでPushするときに

Error: PRC failed; result=22, HTTP code = 413

なるエラーが出てくるときは、GitLabが動いてるサーバーで「 /etc/nginx/sites-available/gitlab 」の「 location / 」に 「client_max_body_size 100M; 」を追加。何故か「 /etc/init.d/nginx restart 」では有効にならなかったので、サーバーごと再起動したら無事にPush出来た。
合わせて、「 /home/git/gitlab/config/gitlab.yml 」の「 production.git.max_size 」を「 104857600 」に合わせておいたほうがいいかも。

413じゃなく

Error: PRC failed; result=22, HTTP code = 411

なるエラーが出てくるときは、クライアント側で「 $ git config http.postBuffer 104857600 」を設定してあげる。

どちらも値はお好みで。

実際には何個か移行出来なかったプロジェクトもあったんだけど、今となってはあまり重要じゃないプロジェクトだったりするんで後から履歴無しでGitに突っ込んじゃった。
それと、プロジェクトはすべて独立させたわけではなく、古いものは1つのプロジェクトにまとめたりもしたから、結構引っかかったのかも。

少しハマった箇所もあったけど、時間をかければなんとか納得できる移行が出来る。

Subversionにしても、GitやGitLabも、やっぱり規模が大きいOSSはハマってもどうにかなるだろうという安心感があって頼もしい。

いやー、オープンソースって本当に素晴らしい。