hg qqueueや--mqを使ってパッチキューを活用する
このエントリはhttp://partake.in/events/902cd6d9-0215-4ea3-b51f-b8ff32e56426:title=の24日目です。
MQ(Mercurial Queue)を使い始めると感じるのがパッチキューを一つしか持てないという窮屈感とパッチキューはバージョン管理を出来ないの?という疑問です。
この二つの不安はhg qqueueと--mqオプションで取り除く事が出来ます。
hg qqueue
MQを使っている方は'hg qqueue'というコマンドを知っていますか?'hg qqueue'はMercurial 1.6から追加されたMQのパッチキューを複数扱うためのサブコマンドです。
パッチキューを一覧する
適当なhgのリポジトリに移動して、パッチキューが何個有るか確認してみます。確認には'hg qqueue --list'を利用します。
$ hg qqueue --list patches (active)
patchesという名前のパッチキューが見えます。patchesはデフォルトのパッチキューです。(active)は現在選択されているパッチキューを指します。
[追記]'hg qqueue'だけでも一覧してくれます。
パッチキューを作成する
では新しいパッチキューを作成してみましょう。作成には'hg qqueue --create NAME'を利用します
$ hg qqueue --create some-feature % hg qqueue --list patches some-feature (active)
新しいパッチキューが作成され、そちらが選択されました。
ちなみに、パッチキューは次の様に管理されています。
.hg/ |-- patches/ # patches用パッチキュー | |-- series | |-- status | |-- some-patches # パッチ群 | |-- ... | |-- patches-some-feature/ # some-feature用パッチキュー | |-- series | |-- status | |-- some-patches # パッチ群 | |-- ... | |-- patches.queues # パッチキューの名前一覧が管理されている。
[追記]'hg qqueue -c NAME'直後(パッチキューにパッチが一つも無い状態)の場合、ディレクトリが作成されないので注意が必要です。'hg qnew'でパッチを作成するとディレクトリが作成されます。
パッチキューを切り替える
別のパッチキューに移る場合は'hg qqueue NAME'を利用します。patchesに切り替えてみましょう。
$ hg qqueue patches % hg qqueue --list patches (active) some-feature
patchesに切り替えられました。
切り替えの注意点としては、リポジトリに未コミットの変更がある場合、パッチが適応されている場合はパッチキューの切り替えは行えません。'hg qpop --all'を利用してパッチを取り外してから切り替えましょう。
$ hg qqueue --list # 初期状態はpatches patches (active) some-feature $ touch a $ hg add a $ hg qqueue some-feature # 未コミットの変更がある場合は切り替え出来ない abort: patches applied - cannot set new queue active $ hg qnew some-patch $ hg qqueue some-feature # パッチが適応されている場合も切り替え出来ない abort: patches applied - cannot set new queue active $ hg qpop --all # パッチを全て取り外す popping some-patch patch queue now empty $ hg qqueue some-feature $ hg qqueue --list # 切り替え出来た! patches some-feature (active)
ちなみに、Mercurialは親切なので、存在しないパッチキューに切り替えようとすると「作れば?」とアドバイスをくれます。
$ hg qqueue not-exists-queue abort: use --create to create a new queue
--mqオプション
Mercurialの様々なサブコマンドに存在する--mqオプション、このオプションの存在意義について疑問を抱く方は多いと思います。実はこのオプションはパッチキューをバージョン管理する場合に役に立つオプションなのです。
パッチキューをバージョン管理する。
現在選択しているパッチキューをバージョン管理するには'hg init --mq'を利用します。
$ hg qqueue --list patches some-feature (active) $ hg qnew first.diff $ hg init --mq adding .hg/patches-some-feature/first.diff
パッチキューのリポジトリがどのような状態か'hg status --mq'で調べてみましょう。
$ hg status --mq A .hgignore A first.diff A series
ファイルが追加されていますね。'hg commit --mq'でコミットして履歴を確認してみましょう。
$ hg commit --mq -m "initial import" $ hg log -p --mq changeset: 0:4d48afe4ddf4 tag: tip user: Takumi IINO <trot.thunder@gmail.com> date: Fri Dec 23 23:34:29 2011 +0900 summary: initial import diff --git a/.hgignore b/.hgignore new file mode 100644 --- /dev/null +++ b/.hgignore @@ -0,0 +1,5 @@ +^\.hg +^\.mq +syntax: glob +status +guards diff --git a/first.diff b/first.diff new file mode 100644 --- /dev/null +++ b/first.diff @@ -0,0 +1,2 @@ +# HG changeset patch +# Parent f124f111a4682e52c30215634fd58468ecbecdd9 diff --git a/series b/series new file mode 100644 --- /dev/null +++ b/series @@ -0,0 +1,1 @@ +first.diff
新しいパッチを追加してみる
'hg qnew'で新しいパッチを追加してみましょう。
$ hg qnew second.diff $ hg status --mq M series A second.diff
'hg diff --mq'で差分も確認できます。
$ hg diff --mq diff --git a/second.diff b/second.diff new file mode 100644 --- /dev/null +++ b/second.diff @@ -0,0 +1,2 @@ +# HG changeset patch +# Parent 8bd778fced5ba3769c1ed0d60da011fae9157e89 diff --git a/series b/series --- a/series +++ b/series @@ -1,1 +1,2 @@ first.diff +second.diff
コミットします。ついでに'hg glog --mq'でリビジョングラフも確認してみましょう。
$ hg ci --mq -m "add second.diff" $ hg glog --mq @ changeset: 1:224df7eb738f | tag: tip | user: Takumi IINO <trot.thunder@gmail.com> | date: Fri Dec 23 23:40:08 2011 +0900 | summary: add second.diff | o changeset: 0:4d48afe4ddf4 user: Takumi IINO <trot.thunder@gmail.com> date: Fri Dec 23 23:34:29 2011 +0900 summary: initial import
ここまで来れば--mqオプションは何をしているのか想像が付いていると思います。--mqは次のオプションの指定と等価です。
--repository .hg/patches-some-feature
パッチキューを共有する
パッチキューを複数持ったり、パッチキューを手元でバージョン管理する方法はわかりました。ではパッチキューを共有する為にはどうすれば良いのでしょうか?
次の二つのリポジトリが存在するケースを考えます。
- 中央リポジトリA
- 中央リポジトリAのパッチキューのリポジトリPA
同時にクローン
この二つを同時にcloneする為には'hg qclone'を利用します。
$ hg qclone 中央リポジトリA --patches リポジトリPA
後から追加
中央リポジトリAがクローン済みで、あとからパッチキューのリポジトリPAを追加する場合はどうすれば良いでしょうか?
残念ながら、専用の手段は用意されていないようです(知っている人が居たら教えてください)。次の手順を取る必要があります。
$ cd .hg $ hg clone リポジトリPA patches-{NAME} $ cd .. $ hg qqueue -c NAME
[追記]もう一つの方法。hgrcの修正が必要です。うーん、専用のサブコマンドが欲しいですね。
$ hg qqueue --create {QUEUENAME} $ hg init --mq $ hg pull --mq リポジトリPA $ echo [paths] > .hg/patches-{QUEUENAME}/.hg/hgrc $ echo 'defualt = リポジトリPA' >> .hg/patches-{QUEUENAME}/.hg/hgrc
まとめ
'hg qqueue'を利用して複数のパッチキューを扱う方法と、'--mqオプション'を利用してパッチキューをバージョン管理、共有する方法を紹介しました。
Bitbucketユーザであればforkボタンの隣にある「patch queueボタン」の意味、使い方が、なぜ「Forks/queues」というタブが存在するのか、想像が付いたのでは無いでしょうか?
使いたくなってきませんか?