unoh.github.com

Mercurialでバージョン管理

Mon May 12 00:50:51 -0700 2008

stoplightで最大化したターミナル上でzshとscreenとEmacsを立ち上げ、
明朝体フォントでプログラミングするbokkoです。



今回はバージョン管理システムの1つであるMercurialについて紹介します。




ウノウではSubversionとTracを組み合わせて開発を行っていますが、
僕個人では今年の春ぐらいからEmacsやzsh、screenなどの各種設定ファイルをMercurialでバージョン管理しています。



Mercurialとは?




Mercurialは分散型のバージョン管理システムです。
これに対して、CVSやSubversion(以下SVN)は集中型のバージョン管理システムにあたります。
分散型と聞くと難しそうなイメージがわくかもしれませんが、
CVSやSVNに比べてると、より手軽にバージョン管理を行うことができるというのが、
Mercurialに対する僕の印象です。というのもCVSやSVNでは、まず単一のリポジトリを作成した後、
バージョン管理したいファイルをリポジトリにimportして、コピーをチェックアウトし、
コピーを編集してからその差分をリポジトリにコミットします。
これに対して、Mercurialではバージョン管理の対象そのものがリポジトリになります。
このため、単に1つのマシン上で編集の履歴を保持したりするだけの場合、
集中型よりも手軽に扱うことができます。もちろん、複数のマシンでファイルの同期を取るといったことも可能です。




とりあえず使ってみる




概要だけではあまりピンとこないと思いますので、実際に使ってみましょう。
使用しているMercurialのバージョンは1.0です。
例えば、以下のディレクトリでバージョン管理を行いたいとします。



$ pwd
/Users/username/mercurialSample
$ ls
test.txt
$ cat test.txt
test
$


リポジトリの初期化




リポジトリの初期化は下記のコマンドを実行するだけです。



$ hg init
$



何も表示されませんが成功すれば.hgというディレクトリができているはずです。
バージョン管理をやめたくなったらこのディレクトリを削除するだけでOKです。



$ ls -a
.               ..              .hg             test.txt



また、initコマンドで初期化しただけでは、test.txtはリポジトリには追加されていません。



$ hg status
? test.txt
$



addとcommitでリポジトリにtest.txtを追加します。



$ hg add test.txt
$ hg status
A test.txt
$ hg commit -m "test" test.txt
$ hg status
$


基本的なコマンド




ファイルの追加や削除、差分の更新やコミットはCVSやSubversionとほとんど同じなので、
CVSやSVNを使ったことのある人なら特に困ることなく、使えるでしょう。



$ hg add test.txt
$ hg remove test.txt
$ hg update test.txt
$ hg commit test.txt
$ hg diff test.txt


リポジトリの複製




上記のように特に分散型というのを意識せずに単純に個人でローカルだけで
手軽に差分を保持するということができるのも僕がMercurialを気に入っている理由の一つですが、
もちろんCVSやSVNのようにネットワークを介した複数のマシンの間で同期を取ることもできます。
ここでmacというホストとubuntuというホストの間でさっきのリポジトリを共有することを考えてみましょう。
何故macとubuntuかと言うと、実際に僕がMacとParallesDesktopにインストールしたUbuntuとの間で、
Mercurialを使って設定ファイル等の同期を取っているからです。
まず、mac上にある先程のリポジトリをubuntu側から複製してみましょう。
リポジトリを複製するにはcloneコマンドを使います。



$ pwd
/home/username
$ hg clone ssh://username@mac//Users/username/mercurialSample mercurialSample



macがホスト名、/を一つ挟んだ後の文字列がリポジトリのルートディレクトリへのパス、
その次が複製側で作成するリポジトリのルートディレクトリの名前です。
問題がなければ、これで上記コマンドを実行したubuntu側のディレクトリに
リポジトリができます。また、このリポジトリの.hgにあるhgrcというファイルに
どこからリポジトリを複製したのかが記録されています。



[paths]
default = ssh://username@mac//Users/username/mercurialSample



pathsコマンドで確認することも可能です。



$ hg paths
default = ssh://username@mac//Users/username/mercurialSample



ローカルリポジトリの内容をリモートリポジトリに反映




CVSやSVNではチェックアウトしたコピーから単一のリポジトリに対してコミットを行いますが、
Mercurialでは通常、コミットはローカルのリポジトリに対してのみ行います。
単にコミットしただけでは別のマシンのリポジトリに変更内容は反映されません。
前者のリポジトリをローカルリポジトリ、後者のリポジトリをリモートリポジトリと言います。




例えば、さっき複製したubuntu側のリポジトリの内容を変更してみます。



$ cat test.txt
test
ubuntu
$ hg status test.txt
M test.txt
$ hg commit -m "add ubuntu" test.txt
$



これでubuntu側のリポジトリの内容が変更されました。
これをmac側のリポジトリにubuntu側から反映させるにはpushコマンドを使用します。



$ hg push ssh://username@mac//Users/username/mercurialSample



pushコマンドが成功したら、mac側のリポジトリでupdateコマンドを使用します。



$ hg update
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cat test.txt
test
ubuntu
$


リモートリポジトリの内容をローカルリポジトリに反映




逆に別のマシンで変更されたリポジトリの内容を自分のリポジトリに反映させるには
pullコマンドを使用します。ubuntu側で変更された内容をmac側から取り込んで見ましょう。



$ hostname
ubunutu
$ cat test.txt
test
ubuntu
more ubuntu
$ hg status
M test.txt
$ hg commit -m "add more ubuntu" test.txt
$


$ hostname
mac
$ pwd
/Users/username/mercurialSample
$ hg pull ssh://username@ubuntu//home/username/mercrurialSample



pullコマンドが成功したら、updateコマンドを実行します。



$ hg update
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cat test.txt
test
ubuntu
more ubuntu
$


ファイル無視の設定




ソースコードなどのバージョン管理をしていると、
一部例外としてバージョン管理の対象に含めたくないファイルが出てきます。
例えば、makeコマンドで生成される実行ファイル、etagsで生成されるTAGS、またEmacsが生成する
一時ファイル(末尾に~が付いたファイルや各種拡張が生成する一時ファイル)などがあります。
Mercurialでは.hgignoreというファイルをリポジトリのルートディレクトリに作成して、
ファイル無視に関する設定を記述することができます。
僕の環境では以下のような設定をしています。



.hgignore



syntax: glob
*~
.semantic.cache
.DS_Store
TAGS



また、僕は使っていませんが、正規表現による指定もできます。



syntax: regexp
^t


.hgignoreの設定を共有する




ただ、上記のやり方だと新しいリポジトリを作成する度に設定ファイルを用意する必要があります。
すべてのリポジトリで.hginoreの設定を共有するには、
ホームディレクトリに以下の内容の.hgrcとさっきの.hgignoreを作成します。



.hgrc



[ui]
ignore=~/.hgignore



.hgrcにはほかにもいろいろな設定を記述することができるので、
興味のある方は本家のチュートリアルを読んでみるとよいでしょう。
日本語版もあります。