彷徨えるフジワラ

年がら年中さまよってます

TortoiseHg の独自機能 〜 変更の退避

このエントリは、Mercurial Advent Calendar 2013 の11日目です。

このエントリでは、前回の「TortoiseHg の独自機能 〜 履歴の圧縮」に引き続き、TortoiseHg が独自に同梱している機能の紹介として、「変更の退避(shelve)」について説明しようと思います。

とは言いつつ、変更退避機能そのものに関する説明がメインになりますので、変更退避機能の使い方に関して詳しく知りたい方は、ウェブ上の情報や、拙著「入門 TortoiseHg+Mercurial」を参照してください(笑)。2012年の Advent Calendar での "Mercurialでshelveを使う" や、"TortoiseHgでshelveを使う" といったエントリもあります。

入門TortoiseHg+Mercurial

入門TortoiseHg+Mercurial

Mercurial における変更退避機能

Mercurial2.8 版から、shelve エクステンションを同梱するようになりました。

しかし、同梱される shelve エクステンションは、これまで shelve エクステンションと呼ばれていたものとは、全く由来の異なるものです。
ちなみに、ソースコードのコピーライトから、同梱 shelve エクステンションは Facebook 由来のものであることがわかります。Mercurial のプロジェクトリーダ Matt Mackall 等が、現在 Facebook に勤務していることもあって、Facebook 由来の新規機能がちょくちょく追加されています(例: 並列 update で使用される worker 機能)。

同梱版/非同梱版の shelve は、以下のような点に違いがあります。

特徴同梱版非同梱版
保存方法 バイナリ形式(バンドルファイル) テキスト形式(パッチファイル)
復旧方法 3-way マージ パッチ適用
衝突時挙動 hg merge によるマージ時と同様 適用できなかったハンク(hunk)の書き出し
対話的退避 不可(2.8.1 版時点) 可能(recored エクステンション併用)

既存のリビジョンを履歴ツリーの別な場所に移動する際に:

上記の両方を使用した(+移動先での衝突解消)経験があれば、「復旧方法」や「衝突時挙動」の違いに関しては、何となくイメージできるのではないでしょうか?

対象ファイルの性質や、作業者の好みによって、*.rej ファイルの書き出しの方が好ましいケースもありますから、必ずしも「3-way マージな同梱 shelve 最高!」という訳ではないかもしれませんね。

対話的退避の得手不得手

先述したように、同梱版の shelve エクステンションは、対話的な退避に対応していません。

実は私自身も、対話的退避機能の追加実装を試みてはいるのですが、複数の変更を選択的に退避するケースでは、思ったように変更内容が復旧できない(あるいは「衝突」扱いになってしまう)可能性があることに気付きました。

おそらく、独立したハンク単位の取捨選択あたりまでは大丈夫な気がしますが、ハンク内の変更から取捨選択するようなケースは、同梱 shelve のような方式とは馴染まない気がします(技術的な詳細に関しては、状況を整理した後で、別途エントリを公開しょうと思います)

さて、TortoiseHg が提供する shelve 機能は、これまで「非同梱の shelve エクステンション」として知らているものを使用しています。

TortoiseHg コミッタの西原さんに確認したところ、今のところは同梱版への対応の予定は無い、とのことです。

ここからは私の推測ですが、GUI という「対話的実行に優れた」インタフェースで機能を提供するにあたって、対話的な退避操作に難のある同梱版 shelve での実装に切り替えるメリットが感じられなかったのではないでしょうか?いくら本体に同梱されているからとは言え、現状で既に動作実績がある非同梱版 shelve の機能を捨てることにもなりますし。

まぁ、単に「面倒 and/or 手がまわらない」だけなのかもしれませんが(笑)。

ちなみに、TortoiseHg の現行の変更退避機能では、退避ファイル A に保存していある変更内容に対して:

  • 作業領域への復旧
  • 他の退避ファイル B への移動
  • 未適用な MQ パッチファイルへの移動

といったことが可能です。また、変更内容の復旧や移動の際にも、対象をハンク単位で選択可能です。

このような特徴は、変更の保存をパッチファイル形式で行っているからこそ得られるものですから、バンドルファイル形式で変更を保存する同梱版 shelve を使った実装への移行は、当面は無いものと考えても良いでしょうね。