【速い、簡単、気持ちいい のMercurial!】

Last modified Tue Feb 14 12:08:05 2012 on firestorm


神経質で面倒臭がりのちみ用のSCMはMercurialで決まりだ

こんなことを感じたことがあるなら、今すぐMercurial使うべし。

  1. よくファイルをなくしたり中味おかしくしちゃったりするので、 バージョン管理システムってのを使ってみたいが そもそもどうやって使うのか知らん。

  2. CVSやSubversionを既に使っているが、

  3. CVS? svn? なにをいっちょる、RCSで十分じゃボケ、 Simple is best!

まず分かりやすい1と3から。ユーザの視点から見ると、

MercurialはRCSと同じくらいシンプル!

なのである。たとえばあるファイルを 急にバージョン管理したくなったとする。 状況によって微妙な違いはあるが、 RCS, Mercurial, CVS, Subversion によるファイルコミットまでの ステップを示すと以下のようになるだろう。

RCSMercurialCVS Subversion
リポジトリ作成mkdir RCS
(省略可)
hg init cvs -d /repo init svnadmin create /repo
ファイルの登録
ci -u file
hg add file
hg ci
export CVSROOT=/repo
mkdir newdir
cp file newdir
cd newdir
cvs import newrepo v r
cd ..
rm -rf newdir
cvs co newrepo
mv newrepo/* .
rmdir newrepo
   

mkdir newdir
cp file newdir
cd newdir
svn import file:///repo newrepo
cd ..
rm -rf newdir
svn co file:///repo/newrepo
mv newrepo/* newrepo/.svn .
rmdir newrepo
修正開始
co -l file

(常に ci -l するなら不要)
なしなしなし
コミットci -u file
hg ci
cvs ci
svn ci

なんかCVSとSubversionが極端にステップ多いように感じるが、 実際のところは新規リポジトリを作ったり、importでファイル登録するのは 最初の一回だけで済むから、そんなに違うわけではない……が、 「最初の一回だけ」ってところがミソで、

滅多にやらないからよく忘れる。

importのときのリポジトリでのディレクトリ名とローカルディレクトリ名の 関係とかを確かめるために毎回実験してから作業するので二度手間。 今回上の表のcvsとsvnの部分を作るのに20分くらいかかって 泣きそうになった。おまけにどっか間違えてるかもしれん。

いっぽう、RCSとMercurialは、これらの手順忘れるか? ってくらいシンプル。そうでなくてもまず、間違えない。 もし間違えたとしても

(RCSの場合)
rm -f RCS/file,v
(Mercurialの場合)
rm -r .hg

としてやり直すだけでいいので、間違いに対する恐怖が断然小さい。 実はわしはCVSらぶらぶになったあとも個人管理のファイルは好んでRCSを 使っていた。だって、ご破算が簡単にできるから。Mercurial も同じくらい簡単。

お試し修正もお手の物!

さて、リポジトリにたくさん履歴が入ったぞ。するとリポジトリ 自体がすごく大事になって、失敗してももうご破算って訳には行かなくなる。 ちょっと自信のない修正やリポジトリに対する 操作(ブランチを作るとかマージするとか)をしたくなったとする。

どうする?

  1. こわいからそういうことはしまてん!

  2. 気にせずやっちゃえ〜、おかしくなったらなったでしゃーない♪

  3. 他のリポジトリで似た操作を練習してから本番環境でやる。

  4. リポジトリのバックアップを取ってからやる。

  5. 世の中CVS/svnの操作を完ぺきに覚えられないバカがいるなんて 信じられない。当然私はどんな複雑な操作も絶対に間違えない。 私はミスターパーフェクトなのだ! (眼鏡キラーン)

ま、現実的には3か4やね。そんなとき、Mercurialはリポジトリの クローンを作ってそこで実験して、うまく行ったら書き戻す、 失敗したら捨てる、ということができる。

hg clone . /tmp/repocopy      (クローン作成)
pushd /tmp/repocopy           (一時的にクローン側にchdir)
(操作色々)
hg ci
(操作色々)
hg ci
(以下同様)....
(うまくいったなら)
hg push                       (変更点を元リポジトリに送り込む)
popd                          (元のディレクトリに戻る)
hg up                         (作業ディレクトリに反映)
(失敗したなら)
popd                          (元のディレクトリに戻るだけ)

(後始末)
rm -rf /tmp/repocopy          (クローンを削除)

クローン側でのコミット結果を hg push で親側に送り込めば すべての作業経過が親側に送られる。

じゃCVSやSubversionではどうする? 1人でしか使っていないリポジトリならリポジトリのディレクトリにいって バックアップを取ってからごちゃごちゃ…、ってことができるが 共同でいじってる場所だとそうも行かない。新しいブランチを作って そこでいじくる、ってことになるけど、ボツになるようなものは 作りたくないし、もしボツになって svn rm ってしてもリポジトリには 履歴が残るから「リポジトリ汚し」になっちゃうやん。「は? そういう 履歴も残してこそのバージョン管理でしょ?」と言われそうだが、 だってだって、神経質なんだからしゃーないやん! いやなもんはいやだー。

精神的ハードルが下がる!

さて、最初に掲げた問題点その2の各項目を1つ1つ当たって行こう。

まずどこにリポジトリを設置するかを考えているうちに 別の仕事が入って先延ばしになってしまう。

新規リポジトリを設置するのがめんどいし、 たまにしかやらないのでやり方思い出すのがたいへん。

せっかく設置してもURLが長いのでよく忘れる。

なんとか思い出しても、新規ディレクトリを最初に import したあと、いったん消してから co し直さないといけないのが 面倒臭いし、一瞬とはいえファイルを消さなきゃいけないのがこわい。

Mercurial では今のディレクトリが同時にリポジトリ。考える必要なし。 普段使っているディレクトリなのでURLを忘れることもない。 既存のファイルを消す必要は一瞬たりとも、ない。これは 前述の表の通り。

思いつきの修正をダメ元で試してみたくなったが、 たぶんダメになるコードが履歴に残るのはやだなあ。 かといって、うまくいったときに履歴に残らないのは困るなあ。

もらったパッチをマージしたい。えーと、 テスト用のブランチとかどうやるんだっけ? ど忘れ。 どこからどこまで当てるんだ? えーと、こうかな? がびーん、間違えた! げー、リポジトリが汚れた。 なかったことにしたーい。

↑みたいに間違って汚しちゃうと嫌なので、 次はもうあんまりやりたくないなあと正直思った。

↑それじゃあんまりなので、まず大がかりなパッチをいじくる ときはリポジトリのバックアップを取ってからやることにした。 って、それならSCM使わない方が楽じゃね?

Mercurialでのお試し修正の例を見て分かるように、「リポジトリ汚し」 の心配をする必要もない。 うまく行ったらその成果をちゃんと書き戻せるし、 失敗したら捨てればよい。とても気楽。

「さあ出先でもバリバリ書くぞ!」と 集中できる環境を整えてやる気が満ちあふれて来たものの、 リポジトリにコミットできないのでたっぷり修正するのを ためらってしまった。

↑こんなためらいが出てしまったので リポジトリにアクセスできるよう出先でもネット接続したら いつものように無駄にWebサーフィンしてしまい、 はかどらなかった。

Mercurialでは作業ディレクトリがそのままリポジトリになるので作業単位 ごとにしっかりコミットできる。一区切り付いたら、あるいは ネットに繋がったら親リポジトリに push すればよい。

それを乗り越えてなんとかたくさん修正して コミットしたが、コミット完了まで遅くていらいらするので コミットのタイミングを先延ばしするようになって コミット忘れが増えた。

Mercurialはコミット処理が圧倒的に速い。 比較記事参照。 ネットワーク越しの場合はネットワーク速度への依存度が高く なるので遅いネットワークでは待ち時間が無視できなくなるのは仕方ない。 ただし(ここ重要)、コミットはローカルリポジトリへの登録なので 毎回サクサク。親リポジトリに反映させたいときには 複数回のコミットをまとめて1回 push すればいいので、 たとえネットワークが遅くても「待つ」ような処理は あまり経験せずに済む。成果をリモートリポジトリに反映させなければ ならないような場合に「こまめにコミット」を徹底しようとしても、 CVSやSubversionではうんざり。

最後の「処理速度」については結構大切だ。 かつてRCSの頃はチェックイン(コミット)がローカルファイルへの操作だったので びしばしチェックインしてもしゃきしゃき動いて気持ちよかった。同じ軽快感が Mercurialでやっと戻って来た。今でもRCSらぶらぶの人は、きっと Mercurialも気に入るはずだ。

公開も楽すぎ!

anonymous ftp のように、匿名アクセスで公開したい。さあ、 どうする。CVSは pserver ですな。Subversion だと、dav かな? davは立てたくないなあ、じゃ anonymous user を作って、えーと どうすんだっけ? って、わしのサイトでも cvs pserver も anonymous ユーザの svn も両方立ててあるんだが、やり方忘れた。 ここに書こうと思ったが、調べ直すのが面倒になった。

はい、Mercurial ではどうする? リードオンリアクセスでの 公開目的ならCGI一発でOK。手順は以下の通り。

  1. ディレクトリを決める。たとえば ~/public_html/hogehoge とする。

  2. CGIプログラムをコピーする。Mercurialのアーカイブに 付いて来る hgweb.cgi をコピー。

    cp hgweb.cgi ~/public_html/hogehoge
    cd ~/public_html/hogehoge
    chmod +x hgweb.cgi
    
  3. コピーしたCGIファイルを開いて編集。

    vi hgweb.cgi
    

    こんな行がある。

    application = hgweb("/path/to/repo", "repository name")
    

    最初の文字列をリポジトリのフルパス、2つ目の文字列を リポジトリに付ける名前にする。え、ほんとにこんだけでいいの??

  4. (Apacheの場合なら)CGIが動くように .htaccess やらを書く。もちろん httpd.conf で AllowOverride してしてあることが必要。

    cat>.htaccess<<_EOF_
    Options	+ExecCGI
    DirectoryIndex hgweb.cgi
    _EOF_
    

以上でおしまい。普通のCGI設置と変わらない。 Apacheじゃなくても動くようだ。この設定だけで、 ブラウザから見るためのリポジトリブラウザと コマンドラインから hg cloneで取り寄せるためのリモートリポジトリ 両方を兼ねてくれる。たとえば 野鳥のhgリポジトリ。 ブラウザで見てもらえるし、そのURLをそのままコマンドラインに叩き込んで

hg clone http://www.yatex.org/hgrepos/yatex yatex

とやってもらえばローカルコピーのでき上がり。楽すぎる。CGIの動く権限と リポジトリの所有者をしっかり分けておけば安心だ。

えなに、「Webサーバの上げ方なんか分からない」だと? うははは、 それでも簡単。

hg serve

で内蔵HTTPサーバが起動する。わお、なんてモダンな設計。 1個のリポジトリ専用サーバにもなるし、 複数のリポジトリを包含させることもできる。httpの場合リードオンリ アクセスとなるのはCGIの場合と同様。まあ実際問題 要らん所にWebサーバなんか上げないのが賢明なので、そんなとき hg serveが役立つ。

にしても pserver とか svnadmin とかややこしいのよく設定したな、エライぞ昔のわし。

まず使ってみる

これまでバージョン管理ツールを使ったことのない人、 最初の出会いがMercurialでラッキー。最初はコマンド3個くらいでおっけー。 試してみよう。

CVSとかSubversionとか使っている人、理屈はいいから、まあ使ってみれ。 「既存のリポジトリは移行できるの?」とか「ブランチはどうやって 切るの?」とか「キーワード置換はあるの?」とかシームレスな移行が どうしても気になってしまうだろうが、解決策はある。 細かいことは後回しにして、サクサク感を味わってみたまへ。 「えー、CVS(or svn)愛してるしー」って思っても、 共存させてハイブリッドで使っても便利。わしだってCVSはブランチ1本で 大きな集合を振り回せるところが大好きだし、svnは svn rm で見た目 消しても時刻指定でちゃんと戻せるタイムマシン的なところが大好きだ。 それぞれ一長一短あるが、Mercurialは使う気持ちよさを後押しする部分が 大きい。うじうじ悩むくらいだったら両方(全部)使っちゃえばいい。 ちなみにこの文書自体はRCS管理だ文句あっか。

基本的な操作は

この3つを覚えておけば十分だ。もし、Emacsを使っているなら hg init; hg add file までやったらあとはEmacs でファイルを開いて C-x v v でどんどんコミットするだけでいい… ってのはRCSやCVSのときと同じ。簡単。

あとは以下のようなのを、使いたいときに選んで使うという程度で 個人使用には十分事足りる。

このくらいかな。hg help と打つとサブコマンド一覧が 出てくるし、hg help サブコマンド と打つと そのサブコマンドのヘルプが出てくるのはsvnなんかといっしょ。あと、 svnと違ってmanが充実しているので困ったときは即座に説明が得られる。

もっと説明書きたいことはあるが、細かいことは 気に入ってからチュートリアルを読めばすらすら頭に入るはずだから、 もうこのへんにしとこう。とにかく重要なのは、RCSのときと同じ軽快感で バージョン管理できるという気持ちよさと、初期設定の異常なほどの簡単さ が群を抜いているということだ。Mercurialにすると、じゃんじゃか 新規リポジトリを起こしたくなる、じゃんじゃか コミットしたくなる。この気持ちよさは仕事の効率に大きく影響すると思う。 試してみれ。


yuuji@example.org
Fingerprint16 = FF F9 FF CC E0 FE 5C F7 19 97 28 24 EC 5D 39 BA
HIROSE Yuuji - ASTROLOGY / BIKE / EPO / GUEST BOOK / YaTeX [Tweet]