何かと便利なshelveのはなし

何をするコマンド?

作業コピー上で行った変更を、一時的に退避するためのコマンドです。個々のファイル内の変更を、部分的に選択して退避することができます。
git stashやhg shelveの仲間ですね。

使い方

shelveを実行すると、以下のように変更箇所(ハンク)が順番に表示されます。
それぞれの変更に対して、退避するならy、作業ツリーに残すならNで応答していきます。

$ bzr shelve -m "foo機能の実装方針を検討するためのコード"
[]--- scripts/tbzrcommand.py 2011-07-23 22:56:53 +0000[]
[]+++ scripts/tbzrcommand.py 2011-12-07 10:30:09 +0000[]
@@ -147,7 +147,7 @@

'add' : ('tbzrcommands.cmd_add',
'cmd_add', 'selected_list',
[]- invoke_add, True),[]
[]+ invoke_add, False),[]

'annotate' : (QBZR_CMDS,
'cmd_qannotate', 'filename',
Shelve? [yNfq?]

・・・(略)・・・

# --allオプションを指定すると、すべての変更がまとめて退避されます。
$ bzr shelve --all
退避した変更セットにはIDが割り当てられ、後でunshelveコマンドで作業ツリーに戻すことができます。
# ID3の変更セットを作業ツリーに戻します。
$ bzr unshelve 3
# IDを指定しない場合は、最後に退避した変更セットが対象になります。
$ bzr unshelve
退避されている変更セットをリストアップするには、--listで。
$ bzr shelve --list
6: BzrLocationクラス関連
5: DragDropHandler関連
2:
Bazaar2.4では、GUIコマンド(qshelve、qunshelve)も追加になりました。
変更を選択して退避する

退避されている変更セットの一覧とその内容を表示する/退避されている変更セットを作業ツリーに戻す

Shelveに関するちょっとしたTips

その1:エディタの使用

bazaar.confに、以下のようにDiffツールを設定しておくと、そのツールを使って退避する変更箇所を選択することができるようになります。

[DEFAULT]
change_editor = C:\Program Files\winmerge\winmergeu.exe @new_path @old_path

コマンドラインでshelveする場合は、yとかNとかを入力するかわりにeを押すと、Diffツールが起動します。GUIの場合は、「エディタを使用」ボタンです。

以下のように、コマンドではひとまとまりの変更として扱われているけれど、その一部だけを元に戻したいという時にも使えます。

※ただし、以下のような、完全に一体化している変更を一部だけ戻すというのはことは出来ません。

その2:revertの代わりに

shelveコマンドの実行時に--destroyを指定すると、選択したハンクを退避せずに、単に作業ツリーから取り除くことができます。

$ bzr shelve --destory
普通、作業ツリーで行った変更を取り消すにはrevertコマンドを使いますが、revertコマンドだとファイル単位での指定しかできません。より細かく取り消す範囲を指定したい場合は、代わりにshelveを使うという手があります。
ちなみに、GUIでやる場合は、「棚に上げる」の代わりに「破棄」を選んでください。

その3:作業内容を一時保存する

コミットする程ではないんだけど、一旦作業コピーの状態を保存しておきたいという場合に、shelveを使うことができます。
unshelveコマンドに--keepオプションを指定すると、変更内容を作業ツリーに戻しつつ、シェルフ内にもそのまま残すことができます。これを利用して、shelveしたあとすぐにunshelve --keepすることで、作業状態をシェルフに記録することができます。

# 全ての変更を一旦退避します。
$ bzr shelve --all -m "2011-12-07 一時保存"
# すぐに作業コピーに戻します。
$ bzr unshelve --keep
これはちょっと面倒ですね。同じように考える人が他にもいるみたいで、バグトラッカに「shelveコマンドに--keepオプションつけてくれよ」っていう要望が上がってます。 → Bug #712449 “bzr shelve should have --keep” : Bugs : Bazaar

ソースを見たら簡単そうだったので、とりあえず手元で対応してみました。 → http://bazaar.launchpad.net/~hid-iwata/bzr/shelve-keep/revision/6056
そのうちちゃんとテストを書いて本家にマージリクエストを出すつもりですが、そうこうしてるうちに誰か他の人が対応してくれる気も。

番外:簡易パッチキューとして

Bazaarでパッチキューマネージャっぽいことをしようとすると、bzr-loomプラグインとかがあるんですが、そこまで本格的なことをする程でもないというのであれば、shelveを使って簡易パッチキューマネージャ的なことができそうですね。

以上、何かと便利なshelveコマンドの話でした。

明日は「Bazaarで歴史改変」的なアレを予定。あくまで予定ですが。