git-svnメモ

今までgit単体ではそこそこ使ってきたのですが、svnに入れる際はあまり使っていなかったのですが慣れてくると使いたくなったので少し調べてみました。ほとんどマニュアルに書いてあることなのですが、個人的にまとめた方が頭に入るのでまとめておきます。

checkoutする

project/trunk/, project/branches/name/, project/tags/name/といった構成になっているときは、cloneするときに-sオプションを指定するとよいかんじです。

$ git svn clone http://svn.coderepos.org/share/lang/perl/HTTP-Engine/ -s

これで、

$ git branch -r 
  class-component
  class-componentrelease-0.0.5
  interface-declare
  lazy_request
  moose
  proxy_request
  tags/release-0.0.1
  tags/release-0.0.10
  tags/release-0.0.11
  tags/release-0.0.12
  tags/release-0.0.13
  tags/release-0.0.13_1
  tags/release-0.0.13_2
  tags/release-0.0.14
  tags/release-0.0.15
  tags/release-0.0.16
  tags/release-0.0.17
  tags/release-0.0.2
  tags/release-0.0.3
  tags/release-0.0.4
  tags/release-0.0.5
  tags/release-0.0.6
  tags/release-0.0.7
  tags/release-0.0.8
  tags/release-0.0.9
  trunk

のようにgitにsvnリポジトリのtagやbranchとして認識させることができます。

標準じゃない構成のときは-T, -b, -tオプションで指定します。

例えば、plaggerみたいなtrunkだけproject/trunk/projectみたいな構成になっているやつの場合、

git svn clone http://svn.bulknews.net/repos/plagger -T trunk/plagger -b branches -t tags

でいけるみたいです。

非常にcloneに時間がかかるので-rオプションでリビジョンを指定して途中から取得することもできるようです。

$ git svn clone http://svn.bulknews.net/repos/plagger -T trunk/plagger -b branches -t tags -r 2000
$ git svn fetch # r2000以降を取得する

ただし履歴がないので、非推奨とマニュアルには書いてあります。また、-sなどを指定していてもそのリビジョン移行でコミットされたbranchなどしか認識されません。

masterをtrunkにする

cloneした段階では、自動的にすべてのコミットがmasterに入っていて、git svn infoしてみると、HEADのurlがtagsのところになっていたりすることがあります。このままdcommitしてしまうとtagsにコミットしてしまうので注意が必要です。

そこで、次のようにしてtrunkのコミットだけにします。

$ git reset --hard remotes/trunk

あるいは、

$ git co trunk -b ltrunk --track

のようにしてmasterはつかわず、trunkに変更を加えるときはltrunkを起点として使うようにするというのもよいかなと思います。後者の方法はtrunkだけじゃなくbranchなどに変更を加えるときにも使います。名前はtrunkでもよいのですがリモートブランチとローカルブランチの名前がかぶるとやや面倒なのでlをつけてます。

最新情報に更新する

全branchなどの更新情報も取得するためにgit svn fetchを使うのがよさそうです。git svn fetchだけだと手元のファイルは更新されないので、作業前に、git svn rebaseして手元のbranchを更新します。

git pullを使うこともできるのですが、手元のみで加えたcommitがある場合rebaseされてないとリモートのリポジトリと手元のリポジトリの履歴の順番が違うのでdcommitしにくくなるそうです。branch間のmergeをする際もgit mergeでやるのではなくて、なるべくgit rebaseを使った方がよさそうです。git pull --rebaseとgit svn rebaseがどう違うのかはよく調べてません。

注意すること

gitはファイルの移動やコピーなどはコミットの情報に含まれてはいないので、git svnsvnリポジトリに戻す際はその履歴がsvn側では追えなくなります。( ただし、gitからだと、Hash値を比べてそれっぽい変更を調べることができるはず。SEE ALSO [git-diff -M -C] )

まとめ

色々と制限もあり、普段とは違ったコマンドを使わないといけないのがちょっと残念な気もしつつも、今のところ使い勝手はそれほど悪くないです。

git whatchanged -pとかで最近の変更を追っ掛けられるのはsvn log -vを使うのに比べると(主に速くて)だいぶ良いなと思います。