23rd
超俺専用メモ「rubyのsvn->git gateway再構築方法」
一般化すれば他者にも有益な話題と思われるがとりあえずめどい。
方針
- ありものをつかう
- 回線に優しく
- てっとりばやく
- データロスしない
setup OpenSSH multiple connection sharing
以下の方式ではsvnサーバにつなぎに行っては「あ、やっぱ手元にあったわ」でコネクション切るというのを繰り返す感じなる。git-svn(1)頭悪いな。で、普通にそのままやるとSSHのセッションハンドシェイクが全体の時間に対して支配的になる上に、どう考えても回線の無駄なので、一旦作ったコネクションを使いまわすことで対応する。これはOpenSSHには普通に備わっている機能だ。~/.ssh/configに以下のように書いておく。
Host ci.ruby-lang.org
User svn
Hostname ci.ruby-lang.org
IdentityFile ~/.ssh/id_rsa
PreferredAuthentications publickey
ControlMaster auto
ControlPath ~/.ssh/master-%r@%h:%p
んで
% screen ssh -vAN ci.ruby-lang.org
この窓は開きっぱなしになるので: screen zshとでもして新しい窓を開いてそっちで作業を続ける。
initial retrieval
ではレポジトリを作るところから。
% repo=tmp.git
% git init --bare $repo && cd $repo
% git --bare remote add svn git@github.com:ruby/ruby.git
% cp config config.bak
% /usr/bin/editor config
ここでconfigに以下のように一行加えることで無駄な通信を大幅に減らすことができる。
diff -up config{.bak,}
--- config.bak 2010-08-20 12:42:54.851200417 +0900
+++ config 2010-08-20 12:44:05.561200494 +0900
@@ -5,3 +5,4 @@
[remote "svn"]
url = git@github.com:ruby/ruby.git
fetch = +refs/heads/*:refs/remotes/svn/*
+ fetch = +refs/tags/*:refs/remotes/svn/tags/*
次にすでにgithubにpushしてあるobjectを引っ張ってくる
% git --bare remote update svn
これでもうこのremoteは用済み。以下のようにconfigを直接弄ってremoteを消す。git remote rmはするな。refも消えるからな。
--- config.bak 2010-08-20 12:42:54.851200417 +0900
+++ config 2010-08-20 16:31:22.341199938 +0900
@@ -2,7 +2,4 @@
repositoryformatversion = 0
filemode = true
bare = true
-[remote "svn"]
- url = git@github.com:ruby/ruby.git
- fetch = +refs/heads/*:refs/remotes/svn/*
kick git-svn
以上の下準備をしたら、ようやく普通にgit-svnしてよし。
% git --bare svn init --stdlayout --prefix=svn/ svn+ssh://svn@ci.ruby-lang.org/ruby
% git --bare svn fetch --minimize-connections --quiet
しばらく(数十時間程度)かかるので根性で耐える。NaCl社内からだと2~4時間程度。
setup remote
では今度はpushする側のremoteを作る。
% git --bare remote add github git@github.com:ruby/ruby.git
% git --bare remote update github
これは超一瞬で終わるはず。いちおうpushできるか試してもいい。
% git --bare push --dry-run -- github \
` git --bare for-each-ref --format='%(refname:short)' refs/remotes/svn \
| fgrep -v tags | sed 's|svn/\(.\+\)|svn/\1:\1|' \
`
Everything up-to-date
ここでnon-fast-forwardとか言われてエラーになるようだったらぶっ壊れてる。リモートかローカルかは不明だが。
setup crontab
これはgatewayなので全自動で同期されるべきなのでcrontabに突っ込んでおく。
0 * * * * cd tmp.git; git --bare svn fetch && git --bare push --dry-run -- github ` git --bare for-each-ref --format='%(refname:short)' refs/remotes/svn | fgrep -v tags | sed 's|svn/\(.\+\)|svn/\1:\1|'`
cleanup
まずもうsshのコネクションは不要なのでそのscreenはいらない。
あと手でconfigを弄る等かなりきわどいことをしているので、ねんのためfsckとかやっといたほうがいいはず。
% git --bare fsck --lost-found --unreachable
% git --bare gc --aggressive --prune
% git --bare svn gc
% git --bare repack -fAd
repackは趣味で。