このエントリは、Mercurial Advent Calendarの22日目です。
@sabo2と申します。勉強会等には一回も出たことがないので、ほとんどの方に初めてお目にかかると思います。
今回はよろしくお願いいたします。
share拡張の使い方
今回は、私は結構使っているのに日本語のblogの記事とかでは見かけたことがない、share拡張について書かせていただきます。
share拡張とは、複数の作業フォルダから一つのリポジトリの履歴を参照・更新できるようにする拡張機能です。
この拡張はMercurial 1.3以上では標準で添付されていますので、~/.hgrcにshare=と書いておくと有効化されます。
ShareExtension - Mercurial
それでは、早速使ってみましょう。
まず、共有元となるリポジトリを作ります。
saboc:work2 sabo2$ mkdir foo
saboc:work2 sabo2$ cd foo
saboc:foo sabo2$ hg init
saboc:foo sabo2$ echo foo > foo
saboc:foo sabo2$ hg commit -A -m"foo first commit"
foo を追加登録中
saboc:foo sabo2$ echo foo2 > foo
saboc:foo sabo2$ hg commit -m"foo second commit"
saboc:foo sabo2$ hg glog --style compact
@ 1[tip] ec224eaf7180 2011-12-22 04:45 +0900 sabo2
| foo second commit
|
o 0 4896a14915db 2011-12-22 04:45 +0900 sabo2
foo first commit
ベースとなる履歴を作成しました。ここで、早速shareコマンドで履歴を共有する作業フォルダを作成します、
コマンドの形式はcloneとほぼ同じですが、オプションは--noupdate/-Uだけのようです。
saboc:foo sabo2$ cd ..
saboc:work2 sabo2$ hg share foo bar
作業領域の更新中
ファイル状態: 更新数 1、 マージ数 0、 削除数 0、 衝突未解消数 0
saboc:work2 sabo2$ cd bar
saboc:bar sabo2$ hg glog --style compact
@ 1[tip] ec224eaf7180 2011-12-22 04:45 +0900 sabo2
| foo second commit
|
o 0 4896a14915db 2011-12-22 04:45 +0900 sabo2
foo first commit
履歴を共有する作業フォルダができました。なお、このフォルダにも.hgフォルダは存在していて、
中のメタデータにsharedであるという印が付けられています。
さて、早速こちらの作業フォルダでコミットしてみましょう。
saboc:bar sabo2$ echo bar > bar
saboc:bar sabo2$ hg commit -A -m"bar first commit"
bar を追加登録中
saboc:bar sabo2$ hg glog --style compact
@ 2[tip] 9b08ed533683 2011-12-22 04:48 +0900 sabo2
| bar first commit
|
o 1 ec224eaf7180 2011-12-22 04:45 +0900 sabo2
| foo second commit
|
o 0 4896a14915db 2011-12-22 04:45 +0900 sabo2
foo first commit
コミットできました。ここで、元の作業フォルダに戻ってログを確認してみましょう。
saboc:bar sabo2$ cd ../foo
saboc:foo sabo2$ hg glog --style compact
o 2[tip] 9b08ed533683 2011-12-22 04:48 +0900 sabo2
| bar first commit
|
@ 1 ec224eaf7180 2011-12-22 04:45 +0900 sabo2
| foo second commit
|
o 0 4896a14915db 2011-12-22 04:45 +0900 sabo2
foo first commit
元の作業フォルダに戻っても反映されています。このようにして、一つの履歴に対して複数の作業フォルダから参照・更新が可能になりました。
さらに、履歴は同じでもparent revisionが異なっていることが確認できます。
基本的なshare拡張についての説明は以上になります。
共有リポジトリから切り離したくなったとき
Mercurial2.0で、share拡張の中にunshareコマンドというのが追加されました。
このコマンドをどこかの作業フォルダ内で使用すると、共有元の履歴を自分の.hgフォルダへコピーして、履歴は自分のところを参照するように戻ります。
その後は、通常のMercurialのリポジトリとして使用できます。
なお、pathとかは特に設定されないので、hgrcにマニュアルで追加した方がいいでしょう。
共有される履歴の範囲
.hgフォルダをのぞいたことがある方だとわかると思うのですが、この作業フォルダは、'store'フォルダのみが共有されます。
ですので、localtag, bookmark, mqのパッチ等は共有されません。
わかっていればmqのパッチを2系統つけられたりして便利(ShareExtensionのページでは非推奨扱い)なのですが、次に書いた問題があります。
履歴改変は要注意
share拡張にはShareExtensionのページにもありますが、注意点がいろいろ書いてあります。
注意点の要点は"履歴がなくなったら他の作業フォルダがおかしくなるかもしれない"ということにつきます。
さて、履歴が削除されたときにどうなるかを実際にみてみます。
先ほどのfooリポジトリから、rev:2を削除してみます。
saboc:work2 sabo2$ cd foo
saboc:foo sabo2$ hg strip 2
バックアップのバンドルを /Users/sabo2/work2/foo/.hg/strip-backup/9b08ed533683-backup.hg に保存
saboc:foo sabo2$ cd ../bar
saboc:bar sabo2$ hg glog --style compact
警告: 作業領域の親 '9b08ed533683' が未知のリビジョンです!
o 1[tip] ec224eaf7180 2011-12-22 04:45 +0900 sabo2
| foo second commit
|
o 0 4896a14915db 2011-12-22 04:45 +0900 sabo2
foo first commit
親が未知のリビジョンです、と出てきました。作業フォルダbarの親は2だったので、
それが削除されて親がいなくなってしまいました。
いちおうupdateとかはできるのですが、ShareExtensionのページには
こうなってしまった時の回避手段として、debugsetparentというコマンドが記載されています。
このコマンドはデバッグ用のコマンドで、無理矢理現在の作業フォルダの親を指定してしまうコマンドです。
ただ、差分があるはずなのにないと表示されてしまったりの不都合が起きる可能性があります。
昨日久しぶりにそういう状況に陥ってしまいました。。
mqやstripやrebaseなどの履歴改変機能を使うな、と書いてあるのはこうなる恐れがあるからのようです。
なお、ハッシュ値が変わるとダメなので、qrefreshとかhisteditで中身が変わるのもアウトです。
sharedな作業フォルダの.hgの中身
通常のリポジトリと、sharedの.hgフォルダに入っているデータの違いは、以下のようになっています。
- storeフォルダがない
- requiresファイルに"shared"という行が増えている
- sharedpathファイルが増えている ※storeの参照先が絶対パスで記載されている
saboc:bar sabo2$ cat .hg/sharedpath
/Users/sabo2/work2/foo/.hg
なお、勝手にこのsharedpathの中身を相対パスにかえても動作します。
windowsでTortoiseHgをつかってsharedな作業フォルダを作成すると、ここにwindowsの絶対パスが入っています。
ただ、これをcygwinから参照しようと思ったら、こんなことを言われてしまいます。
中止: .hg/sharedpath の参照先 /cygdrive/c/Users/sabo2/work2/C:\Users\sabo2\work2\foo\.hg は存在しません!
こうなった時相対パスにすると、cygwinおよびコマンドプロンプトで参照できるようになります。
ただこうすると、今度はTortoiseHgで開けなくなる(絶対パスでないとダメらしい)ようです。。
むりやりmqを使ってみる
履歴以外は各作業フォルダで固有なので、mqのパッチも別々にあてることができます。
この時どうなるかを見てみます。
まず、一つの作業フォルダでパッチを作ります。
saboc:bar sabo2$ echo bar2 > bar
saboc:bar sabo2$ hg qnew BAR2 -m"bar second commit"
saboc:bar sabo2$ echo bar3 > bar
saboc:bar sabo2$ hg qnew BAR3 -m"bar third commit"
saboc:bar sabo2$ hg glog --style compact
@ 4[BAR3,qtip,tip] ba125581993b 2011-12-22 05:30 +0900 sabo2
| bar third commit
|
o 3[BAR2,qbase] 4668026d9c78 2011-12-22 05:30 +0900 sabo2
| bar second commit
|
o 2[qparent] 9b08ed533683 2011-12-22 04:48 +0900 sabo2
| bar first commit
|
o 1 ec224eaf7180 2011-12-22 04:45 +0900 sabo2
| foo second commit
|
o 0 4896a14915db 2011-12-22 04:45 +0900 sabo2
foo first commit
リビジョン3,4がパッチ管理下におかれています。
これを別フォルダから見てみます。
saboc:bar sabo2$ cd ../foo
saboc:foo sabo2$ hg glog --style compact
o 4[tip] ba125581993b 2011-12-22 05:30 +0900 sabo2
| bar third commit
|
o 3 4668026d9c78 2011-12-22 05:30 +0900 sabo2
| bar second commit
|
o 2 9b08ed533683 2011-12-22 04:48 +0900 sabo2
| bar first commit
|
@ 1 ec224eaf7180 2011-12-22 04:45 +0900 sabo2
| foo second commit
|
o 0 4896a14915db 2011-12-22 04:45 +0900 sabo2
foo first commit
一切パッチ管理下におかれていないかのようなLogが出力されました。
この作業フォルダでもパッチをあててみます。
saboc:foo sabo2$ hg up -r 3
ファイル状態: 更新数 1、 マージ数 0、 削除数 0、 衝突未解消数 0
saboc:foo sabo2$ echo foo3 > foo
saboc:foo sabo2$ hg qnew FOO3 -m"foo third commit"
saboc:foo sabo2$ hg glog --style compact
@ 5[FOO3,qbase,qtip,tip]:3 bf0e83041fb9 2011-12-22 05:35 +0900 sabo2
| foo third commit
|
| o 4 ba125581993b 2011-12-22 05:30 +0900 sabo2
|/ bar third commit
|
o 3[qparent] 4668026d9c78 2011-12-22 05:30 +0900 sabo2
| bar second commit
|
o 2 9b08ed533683 2011-12-22 04:48 +0900 sabo2
| bar first commit
|
o 1 ec224eaf7180 2011-12-22 04:45 +0900 sabo2
| foo second commit
|
o 0 4896a14915db 2011-12-22 04:45 +0900 sabo2
foo first commit
この状態で、さらに元のフォルダに戻ってどのような履歴になっているのか確認してみます。
saboc:foo sabo2$ cd ../bar
saboc:bar sabo2$ hg glog --style compact
o 5[tip]:3 bf0e83041fb9 2011-12-22 05:35 +0900 sabo2
| foo third commit
|
| @ 4[BAR3,qtip] ba125581993b 2011-12-22 05:30 +0900 sabo2
|/ bar third commit
|
o 3[BAR2,qbase] 4668026d9c78 2011-12-22 05:30 +0900 sabo2
| bar second commit
|
o 2[qparent] 9b08ed533683 2011-12-22 04:48 +0900 sabo2
| bar first commit
|
o 1 ec224eaf7180 2011-12-22 04:45 +0900 sabo2
| foo second commit
|
o 0 4896a14915db 2011-12-22 04:45 +0900 sabo2
foo first commit
...パッチの途中から通常のリビジョンが分岐している、かなり怪しいグラフが出てきました。
ちなみにこの状態をTortoiseHgで見てみると、以下のようになります。
なお、この状態でリビジョン4はqpopできますが、リビジョン3はできません。
また、リビジョン3がqtopの時は、通常リビジョン(に見える)子孫チェンジセットが別にあってもqpushできます。
saboc:bar sabo2$ hg qpop
BAR3 の適用解除
適用中の最上位パッチは BAR2 です
saboc:bar sabo2$ hg qpop
中止: 管理対象外のリビジョンが解除対象に指定されました
saboc:bar sabo2$ hg glog --style compact
o 4[tip] bf0e83041fb9 2011-12-22 05:35 +0900 sabo2
| foo third commit
|
@ 3[BAR2,qbase,qtip] 4668026d9c78 2011-12-22 05:30 +0900 sabo2
| bar second commit
|
o 2[qparent] 9b08ed533683 2011-12-22 04:48 +0900 sabo2
| bar first commit
|
o 1 ec224eaf7180 2011-12-22 04:45 +0900 sabo2
| foo second commit
|
o 0 4896a14915db 2011-12-22 04:45 +0900 sabo2
foo first commit
saboc:bar sabo2$ hg qpush
(作業領域の親リビジョンはヘッドではありません)
BAR3 を適用中
適用中の最上位パッチは BAR3 です
メリットとデメリット
私は通常仕事のリポジトリがCVSになってしまっているorzために勝手mercurial管理しているのですが、
チームの変更についていく方の作業フォルダと、自分の作業を行う作業フォルダを分離できるので
アップデートの手間が省けてかなり便利です。
それ以外では、通常は軽い変更を行うときにいちいちcloneするよりは気軽という点、
またstoreフォルダが共有なので、リポジトリのサイズがかなり軽くなるというメリットがあります。
デメリットは履歴改変機能が使いづらくなることでしょう。特にrebaseをやった時に結構な確率で
地雷を踏んでしまう気がしています。。
あとがき
ここまでお読みいただきありがとうございました。
履歴改変機能、という観点から言うとMercurial2.1で入るphases/states StatesPlan - Mercurial (旧LiquidHg)を皮切りにいくつか提案されているMutableHgでどうなるのかが、share拡張機能の観点から言うと不安です。
Mercurial Advent Calendarは、他に参加者がいないようならば、
明日からは神に戻りまして@troterさんになります。よろしくお願いいたします。