2009年10月10日土曜日

Mercurial利用メモ

Python で実装された分散型構成管理システム(SCM)である Mercurial の利用メモです。ここでは VineLinux4.2 へインストールしています。

リポジトリの作成

Mercurial は分散型の SCM なので、どこかのサーバにリポジトリを作成して常にそこを参照する、という必要はありません。管理下に置きたいディレクトリで hg init することで、そのディレクトリがリポジトリになります。ここでは、php の AOP フレームワークである php-aop のソースコードを svn checkout して例にしました。

$ pwd
/path/to/workdir/php-aop

$ hg init

$ hg status
? .build/build.package.xml
? .build/build.rss.properties
? .build/build.rss.xml
? aop/.build/build.properties
? aop/.build/build.xml
? aop/aop.php
? aop/aop_exception.php
(snip)
? tests/test2/Linker.pointcut.definition.php
? tests/test2/UnitTest.php

$ hg add
.build/build.package.xml を追加登録中
.build/build.rss.properties を追加登録中
.build/build.rss.xml を追加登録中
aop/.build/build.properties を追加登録中
aop/.build/build.xml を追加登録中
aop/aop.php を追加登録中
aop/aop_exception.php を追加登録中
(snip)
tests/test2/Linker.pointcut.definition.php を追加登録中
tests/test2/UnitTest.php を追加登録中

$ hg commit
status で "?" が付いて表示されているものが、まだリポジトリに登録されてないファイルです。引数なしで add を実行すると、登録可能なファイル全てが add されます(ここでは .htignore に .svn を設定してるため、subversion の管理ディレクトリである .svn は対象から外れています)。 commit を実行するとデフォルトエディタが起動しますので、コミットログを記入して保存/終了します。

これで fniweb_hg ディレクトリが Mercurial のリポジトリになりました。

pull と update と merge

メインのリポジトリから hg pull して、hg status 等で確認しても、手元のファイルは変更されていません。cvs update の感覚で考えると混乱しますが、pull はあくまでも外部のリポジトリの内容をローカルのリポジトリ(.hg)に取り込むコマンドですので、変更は加わらないのです。ローカルのリポジトリを先頭のリビジョン(head)に更新するには、hg update コマンドを使用します。

また、Mercurialのマージ(ローカルの作業ファイルと、マスタのリポジトリ内容とのマージ)は、基本的に「commit 済み成果ベースのマージ(by フジワラ)」です。

  1. ローカルリポジトリからupdate
  2. ワーキングディレクトリで作業を実施
  3. 作業成果をcommit
  4. マスタのリポジトリからpullによる成果取り込み
  5. 2つの成果をmerge
  6. 衝突を解消してcommit
  7. マージ内容をマスタのリポジトリにpush
mercurialの前にCVSを使用していたときの「ブランチを作成する際に同時にバックアップ用タグを作成し、ブランチ先頭とバックアップタグの差分をトランクにマージする」という手順に近いので、さほど違和感はありませんでした。

hg rollback の利用

Mercirual は、最後の commit をロールバックすることができます。すなわち、commit してから「その変更によって不要になるファイルの remove を忘れてた!」とか「addし忘れたファイルがあった!!」という場合でも、hg rollback して commit をやり直すことができるわけです。

複数ヘッドの発生と解消

ローカルリポジトリの内容を push しようとした際に、下記のメッセージで失敗することがあります。

$ hg push ssh://hisawo@mercurial.example.com//path/to/repository
pushing to ssh://hisawo@mercurial.example.com//path/to/repository/foo
searching for changes
abort: push creates new remote heads!
(did you forget to merge? use push -f to force)
分散型構成管理でハマりがちで、ある意味キモかもしれません。

これは「現在のローカルリポジトリの先頭リビジョンが push 先のリポジトリで新しい head になる(push 先の head が複数になる)」という警告です。まずローカルリポジトリに push 先のリポジトリを pull し、複数ヘッドを解消した上で改めて push します。

注意:メッセージでは "use push -f to force" などと示唆されていますが、push -f をやると先方のリポジトリのヘッドが複数になってしまいます。すなわち面倒を先送りあるいは転嫁するだけなので、この方法は避けましょう。

参考:pullとupdateとmerge, 藤車(複数ヘッド)

hg serve コマンドの利用

Mercurialにはhttpサーバの機能があり、httpプロトコルでのリポジトリ間伝播や、Webブラウザでの閲覧が可能です。ローカルのMercurial管理下のディレクトリに移動して、hg serve コマンドを実行します。

$ hg serve -p 8888
これで、Webブラウザにて http://hostname:8888/ でリポジトリの内容を閲覧したり、そのリポジトリに対して hg clone http://hostname:8888/ といったアクセスが可能となります。

また、この状態ではフォアグラウンドで実行されますので、デーモンとして起動するには -d オプションを使用します。

$ hg serve -d -p 8888
これで、バックグラウンドで http サーバが起動します。

Mercurial1.1から hg serve 機能が大幅に強化され、リビジョングラフも表示されるようになってます。hg serve を使用するなら、1.1以降が超お奨めです。

0 件のコメント:

コメントを投稿