Mercurial 勉強中 (1)

Mercurial の特徴

Mercurialでバージョン管理http://python.matrix.jp/modules/mercurial.html#id3 も参照のこと。

  • 分散型 SCM として設計されている
    • 各レポジトリのチェックアウトはおのおの(基本的に)独立している;独立して生きていける
  • Subversion のように中央集権的レポジトリを作れない,というわけではない
    • 各作業者が「マスターレポジトリ」の共通認識をもてばよい(そこから clone してきて pull / push するのだ,と)
  • レポジトリのセットアップ等がかんたん
    • レポジトリのセットアップは管理したいフォルダに移動して hg init とうつだけ(その後 hg addremove したり)
    • 分散管理ではなく自分だけで管理するなら RCS 並,いやそれ以上に簡単
  • レポジトリデータは,レポジトリのトップディレクトリの直下の .hg というディレクトリのみにおかれる
    • ローカルだろうがリモートだろうがレポジトリごと複製/移動したい場合,極端な話 cp -R / scp -r してしまえばよい
  • ほぼ Python で書かれている
    • 一部 OS レベルの処理とバイナリファイルを扱う処理で C のコードがある(0.9.5 で 5 つほど)
  • コマンドラインインタフェースのコマンド名は hg(名前の由来は⇒ http://www.pshared.net/diary/20080104.html#p01

軽さだのなんだのはまだ実感するほど使いこなしていません。

MercurialSubversion (SVK) の違い

SubversionSVK を組み合わせると分散レポジトリ管理ができるようになりますが,それでもやっぱり感覚的に違う部分があるので図におこしてみました。


  • Subversion (svn) の場合,checkout の際は指定したリビジョン(省略時は HEAD)のスナップショットを取得します
  • Subversion の場合,working copy の各サブフォルダに管理用フォルダとして .svn がおかれます
  • Mercurial の場合は,working copy 直下の .hg のみが管理用フォルダです
  • SVK については,あえて一般的と思われる local copy を作る方式を記載しました*1
    • mirror repository から直接 checkout する方法もあります(⇒ http://coderepos.org/share/wiki/FAQ/svk)。この場合,ユーザの使用感としては svn を使う感覚で update / commit するだけですむようです*2 *3

Subversion (SVK) ユーザのための Mercurial

SCM はどのソフトウェアもだいたい同じようなコマンドラインをうけつけるようになっています。しかし hg には svn (svk) と異なるいくつかの注意すべき点があります。

  • checkout (co) の代わりに clone
    • ただし svn co と違って,レポジトリ全体(全履歴)を取得します(上記参照)
    • svk copy //REPO1 //REPO2hg clone REPO1 REPO2
    • checkout 自身は updateエイリアスになっています
  • import はパッチセットをインポートするためのコマンドになっている
    • しいていうなら addremove を初回に実行するとその代わりになります
  • svk push / pull は同様に hg push / pull
    • ただし svk push -C の代わりに hg out
  • HEAD に近いキーワードは tip。ただしコンテキストによって意味が変わるので parents のほうをよく使うかも。
  • Mercurial は空ディレクトリを管理対象に含めることができない - daily dayflower

ほか,似ているところ,違うところなど。

hg clone A B と cp -R A B はどう違うのか

hg clone の場合,レポジトリのコピー元に関する情報が記載されます。((実はこのように一段 clone するだけだと clone 元の default path と同じになるので cp -R したときと等価になります。しかし複数段 clone した場合には直 clone 元が default path になるという違いがでてきます。))

% ( mkdir hello && cd hello && hg init )

% hg clone hello my-hello

% cd my-hello

% cat .hg/hgrc

[paths]
default = /home/dayflower/src/hello

ですので,hg push | pull | outgoing | incoming 等で対象となるレポジトリを省略した場合,コピー元(親)のレポジトリが対象となります。

% touch a.txt

% hg addremove
adding a.txt

% hg ci -m "a.txt を追加した"

% hg out    # ← 対象レポジトリを指定する必要がないことに注目

searching for changes
changeset:   1:b4c9e5d06c5f
tag:         tip
user:        dayflower
date:        Thu Feb 28 13:35:43 2008 +0900
summary:     a.txt を追加した

hg out(going) というのは,もし hg push した場合に,どの changeset が送信されるか調べるコマンドです。反対に hg pull する前に使うと便利な hg in(coming) というコマンドもあります。ま,それは本筋の話ではなくて,default path が適切に設定されていると,hg push 等する際に,対象を指定する必要がないよ,ということです(svk と同じですね)。


また,hg clone の場合 cp -R と違って,同じファイルシステムにレポジトリが存在する際にレポジトリ内の履歴ファイルはハードリンクになります。

% ls -li .hg/store/data/
total 4
231234 -rw-r--r-- 1 dayflower  users   64 Feb 28 10:00 a.txt.i

% ls -li ../hello/.hg/store/data/
total 4
231234 -rw-r--r-- 1 dayflower  users   64 Feb 28 10:00 a.txt.i

くわしくは hg help clone を参照してください。

*1:図では簡略化して書いてありますが,実際には Mirrored Master や Local copy はローカルマシン上に Subversion レポジトリを構成してそこに入れ込んであるイメージです。ほか色々ややこしい説明は ⇒ svk によるレポジトリ分割の作業記録 - daily dayflower

*2:なので上の図はちょっと不公平ですよね

*3:でも分散…というかミラーリングすることの旨味が減るような

*4:少なくともわたしにとって

*5:プロパティとかどうなるのかまだ検証していません