Mercurial チュートリアル hginit.com の和訳(Subversion Re-education)

もしあなたが Subversion を使ったことがあるなら、Mercurial で混乱することになるだろう。 このチュートリアルでは、Mercurial の動作における最大の違いについてカバーする。 あなたが Subversion を使ったことが無いのであれば、ここは飛ばして次に行こう。

Subversion Re-education

私の会社のプログラマー達が Subversion から Mercurial に変更することを決めた時、私は少年のように困惑してしまった。

最初、私達が変更すべきではないというあらゆる馬鹿な理由を思いついた。私達は中央サーバでリポジトリを維持しなければならないし、その方が安全だろう、と私は言った。わかるかい?私は間違っていた。 Mercurial では、全ての開発者が完全なリポジトリのコピーを彼らのハードドライブ上に持っている。それは実際のところ、より安全だ。どちらにせよ、大半の Mercurial チームは中央リポジトリを使うし、さらに、衝動的にバックアップする事も出来るし、サイロンとストームトルーパーとラブラドールレトリーバー(もしくは、あなたのIT部門が要求するものならなんでも)を備えた三重のセキュリティーゾーンだって作ることが出来る。

「分散バージョン管理のトラブルは、ブランチするのが簡単すぎることなんだ。」と、私は言った。「そして、ブランチ作業は常に問題を引き起こす」結局、これも間違いだった。私は閃いたんだ。Subversion でのブランチ作業が問題を起こすのは、 Subversion が マージ作業を行うのに必要十分な情報を持っていないからなんだって。 Mercurial では、マージ作業は無痛で簡単で、そしてブランチ作業は普通の事で無害なんだって。

この時私はこう言った。「素晴らしい。使うよ。だけど私には理解できそうもないな。」そして私はヤコブに、私が普段 Subversion で行っていた全ての作業と同等のことを Mercurial で行う方法について一覧にしたカンニングペーパーを作ってもらった。

今、私はこのカンニングペーパーをあなたに見せることができるが、見せないことにした。なぜなら私の脳みそはそれのせいで数ヶ月間もめちゃくちゃになっていたのだから。

もしあなたが Subversion を使っていたのなら、あなたの脳みそはちょっと、うーん、丁寧に言うにはどうすればいいのかな?つまり、あなたの脳みそはダメージを受けているんだ。いや、丁寧じゃない。あなたにはちょっとした再教育が必要だ。私はダメージを負った脳みそで MercurialSubversion よりも複雑だと考えながら、6ヶ月くらいあちこち歩き回っていた。しかし、それはただ単に私がどのように動くのかを理解していなかっただけであり、一度わかってしまえば、ほら!本当に簡単な事だったんだ。

だから私はあなたのためにこのチュートリアルを書いた。Subversion の観点から説明しないようにとても注意しながら。だってこれ以上脳みそにダメージを与える理由なんて無いのだから。世界はもう十分なくらいに脳みそにダメージを与えているんだからね。代わりに、Subversion から来た何人かのために、最初にこの一章を用意した。あなたがきれいな状態から Mercurial を学べるようになるくらいにダメージを回復させるために。

もしあなたが Subversion を使ったことが無いのなら、何も失わずにここを飛ばして次に章(Ground Up Mercurial)に行くことができる。

いいかい?OK、それではショートクイズを始めよう。

Question 1. あなたは完璧なコードを最初から書けますか?

もしあなたが question 1 に Yes と答えとしたら、あなたはとんだ嘘つきか、ずるい奴だ。あなたは失格。テストをもう一度やるように。

新しいコードはバグだらけだ。まともに動くには時間がかかる。そしてその間、それはチームの他の開発者のトラウマの原因になる。

そして、これがSubversion での作業のやり方だ。

  • あなたが新しいコードをチェックインすると、他の全員がそれを手に入れる。

あなたの書いた新しいコードはバグがあるので、以下のどちらかを選ばなければならない。

  • あなたはバグのあるコードをチェックインして、他の全員を狂気へと駆り立てる、か
  • 完全にバグがとれるまで、チェックインをしない。

Subversion はあなたに常に恐ろしいジレンマを与える。書かれたばかりの新しいコードでリポジトリをバグだらけにするか、 もしくは、書かれたばかりの新しいコードをリポジトリに入れないかだ。

Subversion ユーザであるため、私たちはそのジレンマが存在しない事を想像出来ないくらいに、このジレンマに慣れている。

Subversion チームのメンバーは、数日から数週間も何もチェックインしないで過ごす。 Subversion チームでは、ビルドを壊す恐怖や、シニアデベロッパーのマイクのお怒りなどから、新人はコードのチェックインを恐れるようになる。マイクはチェックインがビルドを壊したことで怒り出すと、インターンのキュービクルに怒鳴り込んできて机の上をなぎ払い「お前は今日限りでクビだ!」と叫ぶんだ。

チェックインに関するこの恐怖の全ては、人々が何週間も何週間もバージョン管理の恩恵無しにコードを書いて、チェックイン作業ではヘルプのために熟練した誰かを見つけなければならない事を意味している。もしあなたがそれを使えないのなら、なぜバージョン管理なんてあるんだ?

そこで、Subversion での作業を簡単な図にしてみた。

Marcurial では、全ての開発者が自分用のリポジトリを持ち、彼らのデスクトップの上で作業している。

あなたはあなたが望めばいつでも、あなたのコードをあなたのプライベートなリポジトリにコミット出来るし、バージョン管理のあらゆる恩恵を享受できる。あなたはあなたのコードがちょっとでも良くなったら、それをコミット出来るんだ。

一度コードが信頼出来るとわかれば、あなたは他の人たちに対して進んで新しいコードを使ってもらおうとして、あなたのリポジトリからあなたの変更分を、他の全員が pull するために、中央リポジトリに push する。そしてついにあなたのコードと出会うんだ。準備が出来たときに。

Mercurial は新しいコードのコミットという行為を、他の全員の負担となる行為から分離するんだ。

そしてこのことは、他の開発者があなたの変更を得ること無しにあなたがコミット(hg com)出来ることを意味する。あなたはあなあたの変更の束が安定して良くなったなら、好きな時にそれをメインリポジトリへ push (hg push) すればよい。

もう一つの大きなコンセプトの違い

あらゆる街道がどのように名前を決められるかは知っているよね?

うん、そうだね、日本ではぜんぜん違う。彼らは一般的には道の間の区画を番号付けして、とてもとても重要な道にだけ名前をつける。

同じような違いが SubversionMercurial にもある。

Subversion は リビジョンによって考えることを好む。あるリビジョンはある時点での完全なファイルシステムのように見える。

Mercurialでは、あなたは changesets で考えることになる。ある changeset は、あるリビジョンとその次のリビジョン間にある簡明な変更分のリストで出来ている。

どっちもどっちだけど、何が違うのだろうか。

違いはこうだ。あなたと私がいくつかのコードに対して仕事をしているところを想像して欲しい。そして私たちはコードをブランチし、離れ離れになっている作業場に持って行き、本当にたくさんの変更を別々に作り、結果としてかなりの違いが出来る。

私たちがマージをしなければならない時、Subversion は両方のリビジョン -私の修正したコードと、あなたの修正したコード-を見て、それらをどのようにして粉々にぶち壊してやろうか考える。通常それは失敗するわけだが、実際にはコンフリクトなんてしていないのに何ページも「merge conflict」と表示されて、私たちがしようとした事に対して単純に Subversion がどこで失敗したのかがわかるだけだ。

対照的に、私たちが Mercurial を使って離れ離れに仕事をしていると、Mercurial は忙しく一連の changesets を維持し続ける。そして、私たちがコードをマージしたい時に、Mercurial は実際に全情報以上のものを持っている。それはすなわち、Mercurial は私たちそれぞれの変更内容を知っていて、それらの変更を再適用することが可能で、最終成果物を見ながら、どのようにそれを一緒にしたらいいかを検討したようなもの以上の内容である。

例えば、もし私がある関数をほんのちょっと変更してその関数をどこかよそに移したとしても、Subversion は本当にこれらのステップを覚えていない。そしてマージする時がくると、Subversion は新しい関数が突然現れたように思うことだろう。一方、Mercurial はこれらを全て分けて覚えているので、関数の変更や関数の移動といった、あなたが関数に加えるあらゆる変更について、Mercurial は私たちの変更分をうまくマージする。

Mercurial が changesets に関する全てを考慮するため、あなたは changeset を使って興味深い事をする事が出来るようになる。あなたは、中央リポジトリに変更を push して全員に負担を与えるような事をしなくても、あなたのチームの友人に変更分を push して変更分を試してみる事が出来るんだ。

もしこういった事でちょっと混乱するとしても心配は無い。このチュートリアルが終わるころには完全に理解出来てるから。差し当たり知っておくべき最も重要な事は、Mercurial がリビジョンではなく changeset で考えるからこそ、Subversion よりもずっと適切にコードをマージ出来るって事だ。

そしてその事が意味するのは気軽にマージが出来るということなんだ。だってマージは悪夢にならないからね。

何か楽しい事を知りたい?私がかつて会話したことのあるほとんど全ての Subversion チームは私に非常に良く似ているけどいくつかバリエーションのある話をしてくれた。この話はとても一般的な話なのでとりあえず"Subversion #1"と名づけよう。そのストーリーとはこうだ。ある時点で、一般的には顧客に出荷したバージョンと開発中のコードを分けるために、彼らは彼らのコードをブランチする。そして全てのチームは私にこのように話してくれる。この試みはうまくいくよ、マージをするまでは、と。そして悪夢になる。5つのメモ程度の修正に、結局は6人のプログラマーが一つのコンピュータの周りで2週間も働き続けることになり、全てのバグの修正のために安定ビルドから開発ビルドまで手動で逆戻りさせていかなければならなかった。

そしてほとんど全ての Subversion チームが私に二度としないと断言し、ブランチしないと誓うのだ。そして彼らがやった事はこうだ。すなわち、それぞれの新しい機能は大きな #ifdef ブロックに入れることだ。こうする事で彼らは大きな単一のトランクで仕事をする事が出来るようになるし、顧客は新しいコードのデバッグが完了するまでの間に新しいコード見ることも無い。だが、正直に言ってとんでもない話だ。

安定版と開発版のコードを分離し続けておくというのは、正確にはソースコード管理がサポートしてあなたにやらせてくれることだろう。

あなたが Mercurial に切り替えた時に、あなたは気づかないだろうけれども、ブランチは再び可能になり、あなたは恐れなくともよくなる。

このことは、チームがリポジトリを持つことが可能であり、ある新しい機能のためにプログラマーの小チームが協力し、そしてそれが出来上がり、彼らがメインリポジトリにそれをマージする事が出来るってことで、これは有効だ!

このことは、QAチームがコードを試すためのQAリポジトリを持つことを可能にする。もしそれが動いたなら、QAチームはそれを中央リポジトリに push する。この結果、中央のリポジトリは信頼できるテスト済みのコードを持つようになる。これは有効だ!

このことは、あなたが分離させた実験用リポジトリを動かすことが出来、もしそれが動くなら、あなたはそれをメインのリポジトリにマージする事が出来て、もし動かなかったら、そのコードをあきらめることが出来る。これは有効だ!

最後の大きなコンセプトの違い

MercurialSubversion の間にある最後の主なコンセプトの違いを気にし過ぎることは無いのだが、もしあなたが気づかないとあなたは足をすくわれるだろう。それを以下に示す。

Subversion は基本的にファイルによるリビジョン管理だが、Mercurial ではリビジョン管理は常に全てのサブディレクトリを含んだ完全なディレクトリ全体に対して適用される。

あなたが Subversion に関してこの事に気づくのは、もしあなたがサブディレクトリに行ってあなたの変更をコミットすると、そのサブディレクトリとそのサブディレクトリ以下のディレクトリの変更だけがコミットされるということであり、これはあなたが他のディレクトリで変更した内容を確認し忘れる可能性があることを意味している。一方、Mercurial では全てのコマンドが常にツリー全体に適用される。もしあなたのコードが c:\code にあったら、 hg commitを実行した時に c:\code にいても他のサブディレクトリにいても同じ効果を得ることが出来る。

これは大した問題では無いが、しかし、もしあなたが会社全体を対象とするような巨大なリポジトリを扱うとなると、いくらかの人は関心のあるディレクトリのみチェックアウトして作業するのだが、これは Mercurial ではよいやり方では無い。 - あなたはいくつかのプロジェクト毎に小さなたくさんのリポジトリに分けた方がよい。

最後に

私の言うことを信じなさい。

MercurialSubversion よりベターだ

ソースコードをチームで扱うのによりよい方法だ。ソースコードをあなた自身で扱うのによりよい方法だ。

ただベターだ。

そして、私の言ったことをよく覚えておいて、もしあなたが Mercurial の動作方法を理解したら、そしてあなたが Mercurial のやり方で働き、そしてあなたがそれと戦う事に挑戦せず、古い Subversion のやり方で Mercurial を使おうとするのをやめて、代わりにあなたが Mercurial の期待するやり方で働く事を覚えれば、あなたは幸せになれるし、成功するし、ふっくらとしてくるし、いつでもテレビのリモコンが見つかるようになる。

そして近いうちに、あなたは魅了され、私にはあなたが何をしようとするかわかるが、Mercurial をあきらめて Subversion に戻ろうとする。なぜなら、それは奇妙で、まるで外国に住んでいるようで、そしてあなたはホームシックにかかり、あなたはあらゆる正当な理由を思いつくようになる。例えば、あなたは Mercurial がディスク容量を喰いすぎると非難するけど、実際、一般的には Subversionディレクトリの方がディスク容量を喰うんだよ。(これは本当だ!)

そしてあなたは Subversion に戻るだろう。Subversion のやり方でブランチをしようとして混乱するんだ。うまくいかなかったというのに。あなたは本当は Mercurial のやり方でリポジトリのクローンを作ってブランチをするべきで、 Subversion のやり方でやろうしてはダメで、だから勉強した Mercurial のやり方でやるんだ。私を信じなさい。有効だ。

そしてあなたはヤコブになるか、ヤコブに相当する者になり、あなたに"Subversion から Mercurial へのカンニングペーパーを与え"、数ヶ月をhg fetch が本当は何なのか知りもしないのに、hg fetch が svn up に似ていると考えて、 そしてある日、何かが間違ってしまったことで Mercurial を非難するんだ。本当はあなた自身が Mercurial の動作を理解していない事を非難すべきなのに。

私があなたの将来を知っているのは、私が過去にそれを経験したからである。

同じ間違いをするな。Mercurial を学び、Mercurial を信じ、Mercurial がどのように動作するのかを把握し、そしてあなたは同世代からソースコード管理における成功者に移行するんだ。あなたの競争相手がベンダのライブラリアップデートに対処するために起こった merge conflict への対処に一週間をかけている間に、あなたは hg merge とタイプしてあなた自身に「すげぇ、クールだ、動く」と言うようになる。そしてマイクは落ち着いてインターンマリファナを分け合い、そしてすぐに春が来て、近所の学校の子供たちは衣替えをして、人生がよくなるだろう。

次回:Ground up Mercurial

目次へ