Mercurial フェーズについて

Mercurial Advent Calendar 2013 19日目です。

フェーズ?

たとえばこんなことありませんか

  • 並行作業してて試作用のブランチを間違ってpushしてしまった
  • mqで複数ブランチのパッチを管理しようとして詰んだ

カジュアルにコミットしていらなくなったら削除したいのにpush -bでブランチ指定しないと全部送信されてしまうとかDVCS使っているのに辛いですね。 年末の忙しいときにpush先のリポジトリで操作するとかやりたくないですね。 そこでも操作ミスったら窓から放り投げたくなりますね。 進捗どうですか?

フェーズです。

$ hg help phases

フェーズとはチェンジセット個々に存在する状態で、よくあるパッチワークの誤操作を防ぐためのものです。secret, draft, publicの3つの状態が定義されており、

secret
この状態のチェンジセットはpush, pull, cloneの対象になりません。
draft
コミットされたチェンジセットのデフォルトです。 unbundleしたときもこの状態になります。 意識していなければpublicへ移すまでこの状態です。
public
pushなどで共有されたチェンジセットの状態です。 これになると他の人がチェンジセットを持っているかもしれないので弄るのを諦めて新しいチェンジセットを積みましょう。

また、状態にはpublic < draft < secretと順序があり、あるチェンジセットはそれの祖先のチェンジセットより大きい状態にしかならないという性質があります。 つまり、draftのチェンジセットの子孫はdraftかsecret、secretの子孫はsecretのみになるので、一旦状態を変えたチェンジセットがあればそのブランチ上のそのあとのコミットはフェーズを気にしなくて済みます。

どうやってフェーズを確認するか?

$ hg help phases
$ hg log --debug

チェンジセットのクエリの関数として定義されているので

$ hg log -r "not public()"

とかできます。 GUIだとTortoiseHgでできます。 TortoiseHgまじ便利なので是非使いましょう。

フェーズを変える

$ hg help phases

状態に順序があるので、draftからsecretに上げるには–force付きで

$ hg phase --secret --force REV

とします。secretからdraftに下げるのは

$ hg phase --draft REV

とします。 GUIだとTortoiseHgでできます。 TortoiseHgまじ便利なので是非使いましょう。

あらかじめsecretにする

@flyingfoozyさんからのアドバイス 1 2 を頂いたので追記しておきます。

おなじみの$REP/.hg/hgrcや$HOME/.hgrcに設定を追加することでデフォルトのフェーズを変えることが出来ます。

mqのパッチをsecretにしておきたい

# hg help mq
[mq]
secret = True

コミットをsecretにしておきたい

# hg help config
[phases]
new-commit = secret

またこのコミットだけsecretにしておきたいんだ!という場合は

# hg help commit
hg commit --secret

という方法もあります。 アドバイス頂いてから気付いたんですが、フェーズ周りって情報がまとまっているようで散らかってますね。

個人的なワークフロー

mqでいじっててパッチ消してしまうと死ぬしmqもMercurialで管理するのだるいのでこういう使い方しています。

  1. なにかコミット
  2. フェーズをsecretにする
  3. ...作業...
  4. ベースブランチが育ってきたらHEAD変えてgraft
  5. ...作業...
  6. 一通り作業できたらブランチ切ってmqに突っ込む
  7. 整える
  8. push
  9. 作業につかっただけのsecretなチェンジセットをstrip

こうすると最低2箇所にチェンジセットが存在しているので精神衛生上メリットがあります。 ミスってもgraftしなおせば最悪な状況にはなりません。バックアップ大事。