« 分散バージョン管理の可能性 | トップページ | 3ウェイマージというマージアルゴリズム »

2012/06/18

分散バージョン管理はバージョンではなくリビジョンを管理する

InfoQの分散バージョン管理の記事を読んだ後に、もう一度、JoelがMercurialについて書かれた記事を再読して、ようやく分散バージョン管理が従来のバージョン管理ツールと何が違うのか分かったのでメモ。
ラフなメモ書き。
殴り書きの部分は後で直す。

【元ネタ】
分散バージョン管理で間違いないって、ベイビー - The Joel on Software Translation Project

JoelもMercurialを使っている: プログラマの思索

InfoQ: エンタープライズ分野での分散バージョン管理システム

分散バージョン管理の可能性: プログラマの思索

(前略)
分散バージョン管理で実際のところ一番重要なのは、「分散」という部分ではないのだ。
重要なのは、このシステムが「バージョン」ではなく「変更」(注釈:リビジョン)で物事を捉えているということだ。
(中略)
Subversionユーザからこんな話を聞かされたことが何度あったかわからない。「コードをブランチしようと思って、それはうまくいったんだけど、マージする段になったら、もうまったくの悪夢で、すべての変更を1つひとつ手で再び当て直さなきゃならなかった。こんなこと2度とやるものかと誓って、ブランチの代わりにif文を使う新しい手法を開発したんだ」
時には彼らが自分の開発したトランク1つのやり方を誇りに思っていることさえある。自分の使っているバージョン管理ツールが本来果たすべき役割を果たさない問題を回避したのが美徳でもあるかのように。
分散バージョン管理では、マージは簡単で、うまく機能する。だから安定版ブランチと開発版ブランチを作ったり、あるいはデプロイ前にQA チームがテストするための長期間存続するブランチを作ったり、ちょっと新しいアイデアを試して具合を見るための短期的なブランチを作ったりすることができる。
これは見落としてしまうにはあまりに重要だ。私がここで文章を書くようになってからの10年間に起きた、ソフトウェア開発技術における最大の進歩かもしれない。
(後略)

MercurialがSVNよりも高速な理由の一つは、各リビジョンをパッチで保持しているから、という話を聞いたことがある。
それは、リビジョン全体を保持するのではなくリビジョンの差分をツール内部で保持しているが故に、ログ表示や差分比較、クローンなどの処理が速くなることを意味しているのだろう。

バージョン(つまり、タグ、リリース済みバージョン、ベースライン)ではなく、リビジョン自体を変更管理の対象としていることに分散バージョン管理の本質がある。
ローカルでリポジトリを作れたり、分散した場所でリポジトリを同期できることが重要なのではない。

リビジョン自身を管理しているが故に、コミット履歴の改変と言う分散バージョン管理の黒魔術も生まれる。
ソース管理の本質は、ソース修正のUndo/ReDoが自由に行えること。
同様にコミット履歴をUndo/ReDoできることによって、マージ作業の失敗を恐れることなく、何度でも試すことができる。

Mercurialの黒魔術: プログラマの思索

マージコマンドで一番簡単なものは、PushやPullだろう。
GitHubのPullRequestは、masterから派生したブランチ上でパッチを育んだ後、masterに取り込んでもらうための機能だが、この機能によって開発者が自由にフォークして、コミッタに取り込んでもらうことが楽になった。
でも、PullやPushはマージコマンドとして一番基本的な処理であり、masterの履歴を置き換えてしまう危険がある。
Redmineコミッタの丸山さんが話されているように、PullRequestよりもrebaseを多用する方が良いだろうと思う。

1???Redmine 2.0 リリース ? shinagawa 20120519 v0.1 documentationの「1.36 Mercurialの名前付きブランチ」に、黒色と緑色のリビジョングラフが表示されている。
黒色:default、緑色:stableのブランチと見なすならば、defalutが開発者が触る最新の機能があるブランチ、stableがリリースブランチないし保守ブランチと見なせる。

すると、stable→defaultへマージされた時に、merge with stable のコメントあり。
つまり、stableの修正をdefaultへmergeした。実質はrebaseと思われる。
rebaseの意義は、リビジョンを一直線にすること。

特に、SVNをmasterにしている場合、MercurialやGitのように複数のheadを保持できないため、リビジョンを一直線にせざるを得ない。
すると、masterであるSVNへパッチを取り込む時、rebaseを多用して、masterにパッチを含むトピックブランチを合流させるようにする。

rebaseの利点は、masterの改変履歴をベースにパッチを加工して履歴を維持してくれること。
GitやMercurialでは、単なるソースのマージだけでなく、過去のコミット履歴を判断してコンフリクトを起こさずにマージできる機能があるからこそ、rebaseが実現される。
リビジョン自体を管理対象としているからこそ可能なのだ。

@cointoss1973さんのMercurialのhgsubversion資料でも、リビジョンを一直線にするためにrebaseを使うことを示唆されている。

Mercurialのhgsubversion資料: プログラマの思索

分散バージョン管理はRedmineのようなチケット駆動開発ツールととても相性が良い。
特に、RedmineがVer1.4からマルチSCMリポジトリ対応になって、より相性が良くなった。

従来は、RedmineプロジェクトとSCMリポジトリは1対1対応の設計思想だった。
以前の僕は、trunkという新規開発のコードラインとリリースブランチという保守ブランチをRedmineの複数プロジェクト機能で分けて管理することで、一つのコードライン上の変更作業をプロジェクト単位でまとめて、タスク管理をやりやすくできるようになると考えていた。
しかし、この手法は、ブランチの寿命がかなり長い場合しか有効でない。
トピックブランチのように、特定目的のパッチを作る場合は、ブランチの寿命はとても短いので、ブランチ単位にRedmineプロジェクトを作る方法では、タスク管理がやりやすくなるとは言えない。

だから、マルチSCMリポジトリ機能によって、trunkから派生したトピックブランチやタスクブランチを一つのRedmineプロジェクトでまとめる事ができるので、一つの製品(システム)の変更作業は全て一つのRedmineプロジェクトで管理できる利点がある。
GitやMercurialで、実験的なブランチを自由に作ったとしても、そのブランチをRedmineプロジェクトのリポジトリに追加しておけば、trunkと実験的ブランチの派生関係を記録して残すことができる。

マルチSCMリポジトリ機能はRedmineのたった一つの機能改善に過ぎないが、この機能を有効に活用することで、ソフトウェア開発で最も制御しづらい並行開発を手なずける可能性もあるだろう。
アジャイル開発もその背景には並行開発という難しさが隠れているのだから、分散バージョン管理とチケット駆動開発を組み合わせることで、より強力にアジャイルに開発できる可能性もある。

色々考えてみる。

|

« 分散バージョン管理の可能性 | トップページ | 3ウェイマージというマージアルゴリズム »

Redmine」カテゴリの記事

ソフトウェア工学」カテゴリの記事

廃止Mercurial」カテゴリの記事

構成管理・Git」カテゴリの記事

チケット駆動開発」カテゴリの記事

Agile」カテゴリの記事

コメント

コメントを書く



(ウェブ上には掲載しません)


コメントは記事投稿者が公開するまで表示されません。



« 分散バージョン管理の可能性 | トップページ | 3ウェイマージというマージアルゴリズム »