ネットワークがつながらない状況での分散開発はどうやるのがいいのか

ネットワークがつながらない状況での分散開発はどうやるのがいいかを考えてみる。

以前似たような経験したのは自分たちが複数の協力会社の1つという立場で、元請けのSVNリポジトリに直接コミットするというもの。ネットワークはつながっています。また元請けは基本的に開発はしておらず、協力会社も開発はほとんど終わっていて変更はバグ修正のみという状況です。

イメージはこんな感じ。

リリース(元請けのSVNリポジトリに直接コミット)する場合は、自分たちのSVNリポジトリにタグうってexportして、あらかじめチェックアウトしておいた元請けのSVNリポジトリのソースに上書きしてコミットします。この辺もHudsonで自動化してましたね。あとコミットするファイル一覧も出しました。元請けはそれと実際にコミットされたソースとを比較して漏れが無いか確認してたみたいです。

しかしこの方法だとファイルの削除やリネームに対応できないので、そこはコミット後に手動で元請けのSVNリポジトリから消してました。

最初はこれが面倒だったので元請けのSVNリポジトリから該当するソースツリー一式を消してからコミットするということをやっていたのですが、元請けから差分が見れないと言われ上記の方法に変えました。

今度はネットワークがつながらない状況でどうやるかという話です。今回は自分たちが元請けという立場です。しかもおそらく協力会社からソースを受け取るだけでなく、自分たちからソースを渡すということもありそうです。また開発中も随時ソースを受け取って統合ビルドしたいところです。

で、どうやるのがいいか下記を参考に今考えています。

Mercurial はオフラインの海を越える
http://www.tsunematsu.cc/2010/03/21/2823/

案の一つとして考えているのは、開発者はSVNを見るんだけど構成管理担当者はMercurialを使って、bundleファイルをやりとりするというもの。
SVNMercurialの連携はHgSubversionを使います。Mercurialを使う理由はGitだとWindowsとの相性が心配なことや、TortoiseHgの存在です。情報量的にはGitのほうがよさそうなんだけど。さすがに全部(自社だけ、協力会社だけでも)Mercurialにするのはちょっと敷居が高いと思ってます。

イメージはこんな感じ。

試してみるために自社SVNリポジトリをイメージしてhome-projectを作って、同じ内容で協力会社SVNリポジトリをイメージしたremote-projectを作ってみます。

c:\work>mkdir home-project
c:\work>cd home-project
c:\work\home-project>echo a>a.txt
c:\work\home-project>svnadmin create c:\repos\home-project
c:\work\home-project>svn import file:///C:/repos/home-project -m "Initial import."
c:\work\home-project>cd ..

c:\work>mkdir remote-project
c:\work>copy home-project\a.txt remote-project
c:\work>svnadmin create c:\repos\remote-project
c:\work>cd remote-project
c:\work\remote-project>svn import file:///C:/repos/remote-project -m "Initial import."

次にremote-project側でファイルを変更してコミットします。

c:\svn-work>svn co file:///c:/repos/remote-project remote-project
c:\svn-work>cd remote-project
c:\svn-work\remote-project>echo a>>a.txt
c:\svn-work\remote-project>svn diff
Index: a.txt
===================================================================
--- a.txt       (リビジョン 1)
+++ a.txt       (作業コピー)
@@ -1 +1,2 @@
 a
+a

c:\svn-work\remote-project>svn ci a.txt -m "first remote commit"
送信しています              a.txt
ファイルのデータを送信しています .
リビジョン 2 をコミットしました。

remote-projectをhg cloneします。

c:\hg-work>hg clone file:///C:/repos/remote-project remote-project
[r1] wyukawa: Initial import.
[r2] wyukawa: first remote commit
pulled 2 revisions
updating to branch default
1 files updated, 0 files merged, 0 files removed, 0 files unresolved

これをbundleします。

コマンドで言ったらhg bundle -a remote-project_rev0_to_tip.hgですね。

home-project側でこのbundleファイルを受け取ってhg unbundleするわけですが、まずhg cloneします。

c:\hg-work>hg clone file:///C:/repos/home-project home-project
[r1] wyukawa: Initial import.
pulled 1 revisions
updating to branch default
1 files updated, 0 files merged, 0 files removed, 0 files unresolved

でhg unbundleします。



acceptするとこうなります。

コマンドで言ったらhg unbundle remote-project_rev1_to_tipですね。

この時点で0と2のmultiple headsになります。

hg mergeします。



commitします。

無事にマージされました。

remote-projectで再び変更してコミットします。

c:\svn-work\remote-project>echo a>>a.txt
c:\svn-work\remote-project>svn ci a.txt -m "second remote commit"

このリビジョン2をHgに取り込んでbundleします。コマンドで言ったらhg bundle -r 2 --base 1ですね。-r 2だけだとダメみたい。

これをhome-project側で取り込んでマージするとこんな感じ。

まあ面白んだけど複雑。これで構成管理担当者の運用回るかなあ。

一番原始的なやり方はファイル一式を送る、次はsvn diffを送る、で最後にこの方式かなあと思ってる。