at posts/single.html

個人で簡単に使える分散バージョン管理ツール Mercurial

先日の Trac で OpenID を使う際に、必要に迫られて Mercurial というバージョン管理ツールをインストールした。 正直なところ、バージョン管理には Subversion があるし、「分散」バージョン管理ツールなんて複雑で面倒なだけだろうと思っていた。 でも、ちょっと使ってみたら大間違い。むしろ「分散」なんて意識せずに個人で使うにはとっても向いているんじゃないか。 個人で分散バージョン管理ツールを使うべき理由はこんな感じかな。

  • 「リポジトリ」へのチェックイン、チェックアウトという概念がない。
    • わざわざワークスペースを別に用意しなくていい。
    • 作業しているディレクトリをそのままバージョン管理ツールで管理できる。
  • ネットワークに繋がっていなくてもdiffを確認できる。
  • CGIスクリプトを設置すればレンタルサーバと連携できる(設置にはシェルが必要らしい)
    • WebDAV と違ってHTTPプロキシとの親和性がいい(PROPFINDなどのメソッドをサポートしていなくてもOK)

考えてみれば、 CVS や Subversion は中央にリポジトリを置くモデルなので、 svn-admin で領域を作って、ソースをインポートして、そこからチェックアウトして、と1人で使う分には最初のセットアップがちょっと面倒。 でも、分散バージョン管理ツールの場合はそれぞれのマシンがリポジトリになれる。 ということは、別に他のマシンと連携しなくても、そのマシンだけで完結しているというメリットがあること。

これは使わざるを得ない。 って訳で、一人で使う分で必要になる操作を簡単にまとめてみたよ。 構成は、結城さんのSubversionの基礎練習を参考にさせてもらった。

インストール

Mercurial の公式サイトに Windows 用、 Mac 用、 Debian, Ubuntu, RedHat のそれぞれのバイナリパッケージが置いてあるので、それを入れるだけでOK。

バージョン管理するファイルの作成

まずはバージョン管理したいディレクトリを作って、その中にファイルを追加する。 今回は test1.txt, test2.txt とした。

$ mkdir hgtest
$ cd hgtest
$ vi test1.txt
$ vi test2.txt
$ ls
test1.txt       test2.txt

リポジトリの作成

Subversion が svn というコマンドを使うように、 Mercurial は hg というコマンドを使う。 管理したいディレクトリに移動して、 init コマンドを発行するだけで OK 。 Subversion の svn-admin create と import を同時にやっているような感じ。

$ hg init

これで、カレントディレクトリに .hg ディレクトリが作成され、このディレクトリが Mercurial の管理下に入る。 hg stat で管理状態が確認できる。まだファイルを追加していないので「?」が表示される。

$ hg stat
? test1.txt
? test2.txt

add コマンドでファイルを追加し commit コマンドでリポジトリへ反映する。

$ hg add *
$ hg commit -m 'first import'

この辺は Subversion と同じだなぁ。 面倒なインポートやチェックアウトが無く、作業中のディレクトリをそのまま管理対象にできるので Subversion より最初の敷居が低い。

管理用の .hg というディレクトリが作られている。Subversion と違ってトップのディレクトリのみに作られるっぽい。

$ ls .hg
00changelog.i   requires        undo.branch
dirstate        store/          undo.dirstate

ファイルの差分を確認する

追加したファイルを変更してみる。

$ vi test1.txt

hg diff で差分をみることができる。

diff -r 3b701cee8925 test1.txt
--- a/test1.txt Wed Mar 12 01:31:25 2008 +0900
+++ b/test1.txt Wed Mar 12 01:36:26 2008 +0900
@@ -1,1 +1,1 @@
-hello mercurial
+good night...

変更内容を戻す場合は revert が使える。 revert すると変更中のファイルが .orig として残る。 うっかり revert して作業中のファイルを消した人には助かる機能。

$ hg revert test1.txt
$ ls
test1.txt  test1.txt.orig  test2.txt

あと、ファイルを消した場合は hg update で復活(最後にコミットした状態で)。

コミットと履歴の確認

変更点をコミットしてコミットログを表示。

$ hg commit -m 'test1.txt: hello to good night'
$ hg log 
changeset:   1:bd8bcd244b94
tag:         tip
user:        machu@macbook.local
date:        Wed Mar 12 01:37:00 2008 +0900
summary:     test1.txt: hello to good night

changeset:   0:3b701cee8925
user:        machu@macbook.local
date:        Wed Mar 12 01:31:25 2008 +0900
summary:     first commit

Subversion と違ってリポジトリが手元にあるので、コミットしたリビジョンの diff も簡単に確認できる。

$ hg diff -r 0:1
diff -r 3b701cee8925 -r bd8bcd244b94 test1.txt
--- a/test1.txt Wed Mar 12 01:31:25 2008 +0900
+++ b/test1.txt Wed Mar 12 01:37:00 2008 +0900
@@ -1,1 +1,1 @@
-hello mercurial
+good night...

ファイル名の変更

ファイル名の変更は rename 。svn move と同じかな。

$ hg rename test1.txt test3.txt
$ hg stat
M test1.txt.orig
A test3.txt
R test1.txt

でも commit したら前のファイルも .orig として残った。

$ hg commit -m 'rename test1.txt to test3.txt'
$ ls
test1.txt.orig  test2.txt       test3.txt

ヘルプをみたら copy + remove と書いてあった。

rename       rename files; equivalent of copy + remove

HTTP サーバ

serve コマンドで HTTP サーバが起動する。

$ hg serve

デフォルトポートは8000番。変えたい時は --port オプションで指定できる。

$ hg serve --port 8080

リポジトリの削除

トップディレクトリにある .hg ディレクトリを丸ごと消せば、何事もなかったかのようにバージョン管理していない状態に戻る。

その他のコマンド

その他のコマンド類は help で確認できる。

$ hg help
Mercurial Distributed SCM

list of commands:

 add          add the specified files on the next commit
 addremove    add all new files, delete all missing files
 annotate     show changeset information per file line
 archive      create unversioned archive of a repository revision
 backout      reverse effect of earlier changeset
 bisect       subdivision search of changesets
 branch       set or show the current branch name
 branches     list repository named branches
 bundle       create a changegroup file
 cat          output the current or given revision of files
 clone        make a copy of an existing repository
 commit       commit the specified files or all outstanding changes
 copy         mark files as copied for the next commit
 diff         diff repository (or selected files)
 export       dump the header and diffs for one or more changesets
 grep         search for a pattern in specified files and revisions
 heads        show current repository heads or show branch heads
 help         show help for a command, extension, or list of commands
 identify     identify the working copy or specified revision
 import       import an ordered set of patches
 incoming     show new changesets found in source
 init         create a new repository in the given directory
 locate       locate files matching specific patterns
 log          show revision history of entire repository or files
 manifest     output the current or given revision of the project manifest
 merge        merge working directory with another revision
 outgoing     show changesets not found in destination
 parents      show the parents of the working dir or revision
 paths        show definition of symbolic path names
 pull         pull changes from the specified source
 push         push changes to the specified destination
 recover      roll back an interrupted transaction
 remove       remove the specified files on the next commit
 rename       rename files; equivalent of copy + remove
 revert       restore individual files or dirs to an earlier state
 rollback     roll back the last transaction
 root         print the root (top) of the current working dir
 serve        export the repository via HTTP
 showconfig   show combined config settings from all hgrc files
 status       show changed files in the working directory
 tag          add a tag for the current or given revision
 tags         list repository tags
 tip          show the tip revision
 unbundle     apply one or more changegroup files
 update       update working directory
 verify       verify the integrity of the repository
 version      output version and copyright information

まとめ

「分散」バージョン管理ツールと聞くと、 Subversion などの集中型のバージョン管理ツールよりも難しい印象があったけど、むしろそれよりも分かりやすくて便利。 ブランチやタグや他のリポジトリとの連携は試していないけど、1人で使うだけならそこまで知らなくても十分に使える。 ということで、これまで使っていた個人リポジトリは Subversion から Mercurial へと移行してみようかな。 もちろん、チームで使う場合はこれまで通り Subversion を使うけどね。

はてぶのMercurialタグで関連する情報を調べられる。 こういう珍しい名前だとノイズが入らなくていいね。

関連する日記