まちゅダイアリー
2008-03-11 (火)
■ 個人で簡単に使える分散バージョン管理ツール 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タグで関連する情報を調べられる。 こういう珍しい名前だとノイズが入らなくていいね。
■ Mercurial で1人バージョン管理(複数マシンでの連携編)
作業中のディレクトリをそのまま気軽にバージョン管理できることが、1人だけでバージョン管理を使う時のメリットだと思っているけど、複数のマシンでリポジトリを同期させることももちろんできる。
「分散」リポジトリというだけあって、いろいろ機能がありそうだけど、とりあえず1人で使う時に必要なことだけを覚えた。
リポジトリのコピー
他のディレクトリやマシンからリポジトリを取得する。 Subversion での checkout に近いけど、 Mercurial はリポジトリ全体を丸ごとコピーするところが違う。 リポジトリが大きくなると時間かかりそうだけど、1人で使うレベルなら気にならないかな。 丸ごとコピーなので、コマンド名も clone になってる。 コピーしたいマシン上で clone コマンドを実行。 svn serve や CGI スクリプトで HTTP サーバを立てていれば、 SSH 以外に HTTP でも接続可能。 でも、 svn serve だと書き込みを許可するために設定がいるっぽい。
$ hg clone ssh://192.168.0.211/work/hgtest hgtest requesting all changes adding changesets adding manifests adding file changes added 5 changesets with 7 changes to 3 files 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
コピー元は path コマンドで確認できる。
$ hg path default = ssh://192.168.0.211/work/hgtest
コピーした先でも自由に追加やコミットができる。 この時点ではコピー元のリポジトリへは反映されない。
$ vi test1.txt $ hg commit -m 'text1.txt: update' $ vi test2.txt $ hg commit -m 'text2.txt: update'
現在のバージョン(チェンジセット)は tip コマンドで確認できる。 Subversion での trunk みたいなもの?
$ hg tip changeset: 6:383b26fa4dc6 tag: tip user: matsuoka@ubuntu2.localdomain date: Tue Mar 11 06:01:32 2008 +0900 summary: text2.txt: update
コピー元との差分は outgoing コマンドで確認できる。 -p オプションを付ければ履歴も分かる。
$ hg outgoing -p comparing with ssh://192.168.0.211/work/hgtest searching for changes changeset: 5:e0016f8b092c user: matsuoka@ubuntu2.localdomain date: Tue Mar 11 06:00:51 2008 +0900 summary: test1.txt diff -r 1735accccbf1 -r e0016f8b092c test1.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test1.txt Tue Mar 11 06:00:51 2008 +0900 @@ -0,0 +1,2 @@ +aaaa +aa changeset: 6:383b26fa4dc6 tag: tip user: matsuoka@ubuntu2.localdomain date: Tue Mar 11 06:01:32 2008 +0900 summary: text2.txt: update diff -r e0016f8b092c -r 383b26fa4dc6 test2.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test2.txt Tue Mar 11 06:01:32 2008 +0900 @@ -0,0 +1,4 @@ +aaa +aa +aaaa +
変更内容をコピー元に反映してよければ、 push コマンドを実行する。
$ hg push pushing to ssh://192.168.0.211/work/hgtest searching for changes remote: adding changesets remote: adding manifests remote: adding file changes remote: added 2 changesets with 2 changes to 2 files
変更内容を破棄したければ、コピー先のディレクトリを丸ごと消せば OK 。
まとめ
「分散」になると難しくなるかなーと思っていたけど、実は簡単だった。
- svn checkout, svn commit の代わりに hg pull, hg push を使う
- svn diff の代わりに hg outgoing -p を使う
1人で使う分にはこれで十分な感じ。 あぁ、これ、リモートの Web サイトの管理にも使えるなぁ。 ローカルでファイルを修正して、 hg pull でレンタルサーバに反映させるとか。
グループで使う時にはちゃんと考えて運用しないと大変そうだけど。
"hg add *" のところは,"hg addremove" や "hg commit -A" とか素敵機能もついてまう。
分かりやすくまとめられていますねー^^<br>GITと違ってTortoiseHGがあるのもいいですね。<br>ていうかすでにGIT用のGUIクライアントがあるのか???
>dayflowerさん<br>おおっ。カユいところに手が届く感じなのがいいですね。<br>日記も参考にさせてもらってます。
>dataichさん<br>SubversionでもTortoiseSVN入れたもののほとんど使わずじまいでした。<br>Windowsだと日本語ファイルで問題が起こりそうですね。