仕事で使ってる巨大SVNレポジトリをGithubに移管するためにやったことまとめ

仕事で使っていた4万コミットを超える巨大なSVNレポジトリを、Gitレポジトリに変換してGithubに移管しました。
(※巨大というほどじゃないかもしれませんが自分にとっては巨大だったということで)



今年の6月頃から少しずつ作業して10月にやっと終わったので、あしかけ5ヶ月もかかりました。
(※そればっかり5ヶ月もやってたわけではないです)

一筋縄ではいかずものすごい苦労しました。
他の人が同じ苦労をしなくてすむようにノウハウを公開します。
これから移管しようと考えている人はぜひ私の肩の上に乗っかって楽をしてください(笑)

動機

Subversionで困ってない
ぶっちゃけSubversionで全然困っていませんでした。

コードレビューはちゃんとやっていたし、マージ・ブランチングも自作シェルスクリプトのおかげてスムーズにやれていました。
よく「Gitはマージが賢い、ブランチ作成が一瞬でできる」とかいわれますが、Subversionだってちゃんと使えばコンフリクトなんかめったに起きないし、ブランチ管理・マージだって全然めんどくさくない。
特にver1.7からはサーバもクライアントも大幅に高速化されたし、.svnディレクトリが.gitみたいに1個になったし、rebaseみたいなことだってできる。(sync merge & reintegrate)

ただ、世の中が一斉にGitにシフトしている中でいつまでもSubversionを使っててよいのかという不安がありました。
また、月から金までSubversionにどっぷり使っているとなかなかGitスキルが身につかず、Github上のオープンソースプロジェクトに参加する敷居が高いという問題がありました。
Subversionが腐ったテクノロジーだって??
きっかけはこれ。

会社の腐ったテクノロジーに縛られ続け、VSSやらSubversionやらいまだに使って、レガシーコードに携わっていても、外に出たらそれは評価されるのだろうか?

長時間労働・サービス残業は自分の価値を下げ企業存続を危うくする | Act as Professional - hiroki.jp by HIROCASTER

最初これをみたときは正直腹がたちました。

Subversionが腐ったテクノロジーとは言い過ぎじゃないか、
GreeだってモバゲーだってSubversionで育ったんじゃないか、
Ruby言語は今もSubversionで開発されてるじゃないか、
Subversion1.7からはすごい改善されたのにそれを知らないだけじゃないか、

カッとなって反論記事を書こうとしました。
しかしふと思いとどまって、そんな反論にエネルギーを使うくらいならGit移管をがんばってやってみよう、前に進もう、そう決意しました。
結果的に@HIROCASTERさんに感謝です。

業務でGithubを使うとヤバイらしい
Gihubに移管しよう思ったのは、YAPC::Asia2012でペパポの人がGithubでの開発を楽しそうに語っていたのを聞いたのが決め手でした。
あといつもお世話になっている@sotarokさんの講演動画も。

遭遇した問題点

  • SVNレポジトリ内に不要ファイルが大量に蓄積されており、サイズが肥大化していた
  • SVNでのbranches構成が不規則すぎてgit svn cloneが何度もこけた
  • チームメンバーがGitに不慣れだった

やったこと

  • Subversionレポジトリの整理(不要ファイル削除とか)
  • git svn fetchを使ってSVN→Gitへのレポジトリ変換
  • git-svnで平行運用しつつ、メンバーを教育

Subversionレポジトリの整理(不要ファイル削除とか)

当初レポジトリサイズが6GBもありました。
容量のほとんどは不要な画像とかドキュメント類が占めていました。
svndumpfilterを駆使して不要ファイルをパスベースで除去しました。

svn cp やsvn mvで履歴が複雑に絡み合っている場合、svndumpfilterがエラーを吐くので一筋縄ではいきませんでした。
何段階かに工程を分けて、(まず画像を削除、次にドキュメントを削除、・・みたいな感じで)少しずつ少しずつレポジトリをダイエットさせました。
svndumpfilterを1回通すだけで数時間かかるので作業はかなり大変でした。途中でエラーが出て何度も泣かされました。

svndumpfilterを通算10回ほどかませた結果、レポジトリサイズを6GB→1GBにまで減らすことができました。
差分の5GBはバイナリファイルです。バイナリファイル恐るべし!
参考記事

git svn fetchを使ってSVN→Gitへのレポジトリ変換

最初git svn clone -s でレポジトリ変換しようとしたら、branches構成が不規則すぎてエラーが出まくりました。

git svn clone --trunk でtrunkのみを引っ張ってくるようにしたらうまく行ったのですが、これだとブランチのコミットが全て失われてしまうという問題がありました。
ブランチのコミットを捨てるという選択肢もあるですが、その場合4万コミットのうち3万コミットほど捨てることになってしまい、いろいろ苦労した思い出が消えるのかーと思うとせつなくなってきて、やっぱりできるだけ過去のブランチもGitに移管しようと決めて戦略をねりなおしました。

試行錯誤してみてわかったことは、
  • git svn cloneは使わない。git svn init してからgit svn fetchすれば同じことができるしエラーが出ても途中から再開できる
  • git svn init で--branchesオプションを複数指定できる
これが大発見でした。
この2つのテクニックのおかげで、結果的にほとんどのコミット履歴を維持したままGitに移管することができました。

具体的には、
  • authors変換用のテストファイルを作る
  • git svn init
  • .git/configを手動で編集
  • git svn fetch
authors.txt
tanaka      =   tanaka    <tanaka@example.com>
yamada      =   yamadai    <yamada@example.com>
git svn cloneは使わない方がよい。
実は、
git svn clone = git svn init + git svn fetch
なので、initとfetchを別々に行いました。
init後に.git/configに小細工を加えることで、ブランチ認識ロジックを調整することができます。
.git/configを手動で編集
SVN側で、
branches/dqneo/br1
branches/dqneo/old/br2
のような不規則なブランチ名を使っていたので、これをGitブランチで正しく認識させるのに苦労しました。

下記のようにブランチパスをごにょごにょ書きかえることで、うまくいけました。
先に書いた方が優先的に解釈されるみたいです。
$ cat .git/config
[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
[svn-remote "svn"]
        url = file:///home/dqneo/tmp/repo
        fetch = trunk:refs/remotes/svn/trunk
        branches = branches/dqneo/old/*:refs/remotes/svn/dqneo_old/*
        branches = branches/yamada/old/*:refs/remotes/svn/yamada_old/*
        branches = branches/dqneo/*:refs/remotes/svn/dqneo/*
        branches = branches/yamada/*:refs/remotes/svn/yamada/*

[svn]
        authorsfile = /home/dqneo/authors
なお、下記のような記述は文法エラーになりました。
ワイルドカードがちゃんと使えるわけではないみたいです。
branches = branches/ver*:refs/remotes/svn/ver/*
参考記事

git-svnで平行運用しながらGitに習熟する

スキル高めのメンバーからgit-svnを覚えてもらって、SVNとGitをしばらく平行運用しました。
メンバー全員がGitに習熟するのを待っていると長くなりそうだったので、メンバーのうち半分くらいがgit-svnを覚えた段階で、(なかば強引に)一気にSVNを廃止してGithubに切替えました。

ちなみにGitはこの本で勉強しました。
大変分かりやすかったです。

移管してみてわかったこと

  • Gitはブランチが気軽に作成できるので、コードレビューの粒度が小さくなってよい。
    (SVN時代は1チケット1ブランチだったのでレビューの粒度が大きくて大変だった)
  • SVNに習熟してる人ならGitはすぐ馴れる。
  • Githubはプルリク時にレビューコメントが書き込めるので便利。
    (従来はRedmineにレビューコメントを書いていたのでやりとりが面倒だった)
  • オープンソースプロジェクトへの心理的敷居が下がった。
まだGit/Githubの威力をフルに使いこなせてないので、革命というほどの劇的な変化は生じていません。
(SVN時代にもちゃんとコードレビューする文化があったからかも)

大きいのは、仕事も趣味もGithubに一本化されたので精神的に楽になったことです。

今後使い込んでいくにつれて「ソーシャルコーディング革命」を実感できる日が来るかもしれません。
それを楽しみに日々精進していきたいと思います。
カテゴリ:

人気記事