ぱろっと・すたじお

技術メモなどをまったりと / my site : http://parrot-studio.com/

SubversionのリポジトリをGitリポジトリに移行する

私が一番最初に使ったバージョン管理システムCVSでした


あれがなければ、当時の無茶なチーム開発は不可能だったと思いますが、
使いづらい面もあって、ある程度運用でカバーしなければなりませんでした


それを解決したのがSubversionで、
今の会社に至るまで、公私ともに使い続けていました


しかし、時代は流れ、分散型リポジトリが主流となり、
私自身、数年前から使い出したGitに慣れてしまったのもあって、
もうSubversionには戻りたくありません(´-ω-)


ちょうど、こちらのコラムにもそんな話が

WEB+DB PRESS 総集編 [Vol.1?60]

WEB+DB PRESS 総集編 [Vol.1?60]


現在開発中のシステムはGitで管理しているので、
社内の環境を改めて整備するにあたり、
svn用の環境を再度作るのは面倒だな・・・と


とはいえ、既存システムのコードはsvnで管理されており、
そこには大量の「記録」や「歴史」が残っているので、
それを捨てるわけにもいきません


例によって前置きが長くなりましたが、
svnからgitにリポジトリを移行したときの手順をメモしておきます...φ(・ω・`)

概要


具体的なやり方は以下を見てもらうのが確実です


svn の repository を git の repository に変換する方法 | 株式会社メッサリバティ


基本的にはgit-svnを使えばいいわけですが、
適当にやるとtrunk / branch / tagsの情報が失われてしまいます
(他の記事を見て適当にやってみて、頭を抱えたという・・・)


大雑把な流れとしては以下の通りです

  1. auther変換定義ファイルを作る
  2. svnリポジトリからgitでコードを引っ張り出す
  3. localに作業用リポジトリを切る
  4. svnのtrunkを作業リポジトリのmasterとしてpush
  5. svnのbranchを作業リポジトリのbranchとしてpush
  6. svnのtagsを作業用リポジトリのtagとしてpush
  7. 作業リポジトリを丸ごとどこかにコピーするか、どこかのremoteへpush


以下、適当な作業ディレクトリでやります

cd ~/gittemp

ユーザ変換定義


まず、authers.txtを作ります
svnのユーザ名 = gitのユーザ名」というだけのファイルです

vi authers.txt

parrot = parrot <parrot@example.hoge>

svnリポジトリのclone


次に、svnリポジトリからgit形式でcloneしてきます
もしgit-svnをインストールしてない場合は、先にやっておきましょう
(CentOS5.xの場合はrpmforgeにgitとgit-svnがある)

sudo yum install git-svn

git svn clone -A authers.txt -s [svn-repo-path] [git-repo-name]

「-s」をつけるのが最大のポイントで、
以下の処理が行われます

  • 最後にsvn-commitしたtrunk or branchをmasterとしてclone
    • ここが問題
  • svn-trunkをremote-branchとして定義
  • svn-branchをremote-branchとして定義
  • svn-tagsを「tags/xxx」というremote-branchとして定義
    • remote-branchは「git branch -r」で見える


最後にsvn-commitしたのがtrunkなら問題ないのですが、
branchだった場合、そちらを「git-master」として扱ってしまうので、
そのままpushすると大惨事になりますΣ(゚Д゚;≡;゚д゚)

作業用リポジトリ作成


とりあえず、localでpushするための新規リポジトリを切ります

git init --bare [local-repo-name]

「git init --bare」はremoteで使うリポジトリを作る場合のお約束ですね


これをcloneしたリポジトリにaddしましょう

cd [git-repo-name]
git remote add origin [local-repo-path]

「正しい構成」をこの「origin」にpushしていきます

svn-trunkをgit-masterとしてpush


先ほども書いたように、cloneしてきたmasterは、
必ずしもsvnのtrunkとは限りません


そこで、remoteのtrunkをlocalに引っ張ってきて、
それをmasterとしてoriginにpushします

git branch local-trunk refs/remotes/trunk
git push origin local-trunk:master

svn-branchをgit-branchとしてpush


他のbranchについても基本は同じです
いったんlocalに引っ張ってきて、gitのbranchとしてpushします
全てのbranchについて同じ作業を繰り返します

git branch local-hoge-branch refs/remotes/hoge-branch
git push origin local-hoge-branch:hoge-branch

svn-tagsをgit-tagとして定義


svnのtagsはbranchの一種ですが、
これをgitのtagとして定義し直し、最後にまとめてpushします

git tag hoge-tag refs/remotes/tags/hoge-tag
git tag piyo-tag refs/remotes/tags/piyo-tag
…
git push --tags

作業リポジトリのコピー


ここまでやれば、origin=local-repoに
綺麗な構成のgitリポジトリができています


あとはこれをサーバに丸ごとコピーするなり、
どこかのremoteにpushすれば終わりです