亀岡的プログラマ日記

京都のベッドタウン、亀岡よりだらだらとお送りいたします。

git-svnの自分的運用メモ

前回記事はgit使い始めた導入部分で、今回はどうやって自分が使っているか、です。やはりgitは使わないと覚えられない、理解できなものの筆頭だと思います。なので、業務でも何とか使って行きたいもの。

つまり、git-svnです。

git-svnを使う

git-svnは何も特別なものじゃなくて、ただのコマンドに過ぎませぬ。Gitポケットリファレンスにも記述がちゃんとある、Gitコマンドの一つに過ぎません(実体はperlスクリプトだったはず)。

よっぽどのことがない限り、すでにあるsvnリポジトリを使う、というのがほとんどでしょう。

というわけで、さっくり叩きます。(テストスペースとしてassemblaSVNリポジトリを使ってみてます)

$ git svn clone https://subversion.assembla.com/svn/posaune_testspace_git_svn/trunk

これだけ!簡単ですね。

そしてSVNのupdateはrebaseが対応します。

$ git svn rebase

SVNへのコミットはdcommitを使います。

$ git svn dcommit

git-svnはほんと、これくらいのコマンドしか使わないのですよ。

ブランチ戦略、しましょうか。

最初にgit-svn使ったときは、これだけやって後は単純にgitで変更をコミット → SVNにdcommitの流れをやっていたこともあったんですが、それだけでは単純にgitを使っている感じがしません。コミット粒度もrebaseで調節してやる必要がありますし。

だので、ちょっとくらいはGitっぽく使おう、と思って最近やっているのが以下の戦略です。


  • masterブランチはsvnと定期的に同期する。ローカルでの変更は最後に別のブランチからマージする形を取る。

  • topicブランチを機能毎に作り、開発する。機能が作成完了したタイミングで、まずmasterを最新svnにupdate(svn-rebase)し、そのあとmasterをtopicにrebaseし、最後にmasterとfeatureをマージする。


    • マージ時に–no-ff ; –no-commitオプションを付けることで、変更をまとめる。



後半もうちょっと詳しく見せると、まずtopicで新機能を作成していて、そのときにsvn側で更新されたのを取り込むと、こんな感じになります。

f:id:posaunehm:20120908112641p:plain

masterのHEADみはsvnでの変更が取り込まれていて、その一つ前のコミットからtopicブランチは派生していますね。コミットギリギリまでmasterブランチには追加を入れないので、svnからのrebaseはスムーズに行えています。

ここで、まずtopicブランチをmasterの先頭から派生するようにrebaseします。


f:id:posaunehm:20120908112732p:plain

そうするとこのようにmaster時点で一旦タグが打たれて、その後の追記がtopicで行われているような感じになりますね。(実際にはmasterのHEADコミットからtopicブランチが分岐している、という状態です)


この状態だとマージは容易なのですが、個人のコミット粒度がそのままmasterに乗ってしまいます。そこで–no-ffm –no-comitオプションです。–no-ffによって明示的にマージコミットが作られ、きっちり分岐しているように見せることができます。(ここらへんの設定は@Tomo_phononに色々教えてもらいました)

これでマージするとこんな感じになります。(–no-commitを入れてるのはSVNに入るコミットメッセージをカスタマイズしたいからですね)


f:id:posaunehm:20120908113535p:plain


(ちなみに個々で--no-ffを入れないと以下のようにmasterにブランチの変更がそのまま反映されてしまいます。あとでrebaseで履歴改変してもいいんですけれど、なんとなく、ね。)
f:id:posaunehm:20120908113523p:plain

こうすると、


  • masterブランチ:プロジェクトのお約束事を守る共通空間

  • topicブランチ:自分の自由空間!


と割かしきっちり分けることができます。

メリットとか

まずもって、前回書いた通り、自分の領域を持つことができるのは大きいです。というか、こういう運用にしておかないとDVCSで可能なはずの細かい粒度のコミットができなくなってしまうので非常にぐんにょりですよね。

あと、副次的な効果としては、例えば何かある機能を実装中に既存実装にバグが出た場合でも、


  1. masterからissueブランチとして切り出す

  2. issueブランチで修正 → svnにコミット

  3. 実装中のtopicブランチにmasterをrebase


みたいにすることで、簡単に渡せることになります。

いや、もちろんSVNでも可能なんですが、やはりブランチ作成・切り替え・マージの軽さがこういった動きを凄くやりやすくしてくれます。(個人の感想です)

注意点とか

前回も書いた気がしますが、少なくともgitに関してはコマンドラインと親しむことをおすすめします。定常的に使うコマンドだけでも


  • commit

  • add

  • checkout

  • rebase

  • merge

  • branch

  • reset

  • stash

  • reflog

  • git dcommit

  • git rebase


あたりはほぼ毎日使いますし、これらを軽く扱えるようにならないとブランチ戦略を守った運用は割と難しくなってきます。

大体うまく環境整えばタブ補完も聞きますし、Windows環境だとshコマンドも覚える良い機会なので、できるだけ使っていきましょう。

プログラマなら、コマンドラインに憧れるでしょ??