Mercurialで独立並行リリース管理

Mercurial使ってる人がいたら教えて下さい。

Mercurialは「一部だけ異なる二つのリポジトリ(orブランチ)を 並行して育てて行くことができない」んじゃないかと思うのですが 違いますか?

3/3加筆: 解決。 すごくしっかりしていてCVSやSubversionより確実にできる! でも 前ふりは以前の記述のまま残す。

たとえば、Aというリリースと、A'というリリースがあり、それぞれ 特定部分だけが違うけれども、 同時に対等な立場で進めて行く。Aを使っているときに気付いて修正したものは A'でも必要なので取り込みたい。A'で気付いた修正も然り。こんな感じ。

         修正1          取込2    取込3
A  -------x---------------i-------i--------->
           ↓            ↑      ↑
A' ---------i------------x-------x---------->
         取込1         修正2   修正3

cvsでもsvnでも、範囲を指定したマージができるので、たとえば 今A'で発生した修正3をAに取り込みたいときは 。cvsなら、

cvs up -j 修正2 -j 修正3

svnなら

svn merge -r r修正2:r修正3 <A'のディレクトリ>

とすればOK。どちらも、実際のディレクトリにA'を展開していなくても リポジトリ上のA'に相当するパスを指定してもできる。

さて、Mercurial だが、hg merge の文法はこう。

hg merge [-f] [[-r] REV]
merge working directory with another revision

    Merge the contents of the current working directory and the
    requested revision. Files that changed between either parent are
    marked as changed for the next commit and a commit must be
    performed before any further updates are allowed.

    If no revision is specified, the working directory's parent is a
    head revision, and the repository contains exactly one other head,
    the other head is merged with by default.  Otherwise, an explicit
    revision to merge with must be provided.

Mercurialは、headを1個しか持つことを許さない(マージのときに臨時ででき るもう1個を除く)から必ず完全にmergeしないと先に進めないんだよなー。 だからすこしだけ違うとはいえ、2個のものを独立して進めるのはできない 気がする。

linux-ha Mercurial というところをみると.....

最初の例でいえば、AとA'を各々異なるリポジトリにしたあと、 「修正3→取込3」の地点で、Aのリポジトリでこんな感じ。

hg pull "A'のリポジトリ#修正3"
hg merge
(確認して)
hg ci

#を使って特定のチェンジセットだけ取り込めるようだ。 が、これ、修正3だけでなく、それ以前にパッチ対象ファイルに当てた修正 すべてが取り込まれちゃうようだ。これじゃ困る。 たとえば、ファイルの先頭だけ少し違うままにしときたいのだ。

あるパッチを選択的にやり取りするには、どうも export/import しないと だめみたいだ。

(A'側)  hg export 修正3 > ../diff
(A側)   hg imrpot ../diff

んがー、ダサい。「ちょっとだけ違う部分を含む」もの同士は ちょっと違うってだけで、完全に赤の他人リポジトリとして振る舞わせなきゃ いかんのか?

と2008/2/26に書いたあともしばらく調べていたら解決!

Mercurial and Darcs というところが,ものすごく核心をついた記述になっている。ここを参考に 拡張モジュールの transplant を使えばできると判明。これをつかうには, ~/.hgrc もしくは,リポジトリのトップディレクトリの .hg/hgrc に以下を追加。

[extensions]
transplant =

としたら,修正を取り込みたい方のリポジトリでこんな感じ。

(A側) hg transplant -s (A') 修正3

むっちゃ簡単! 「どのパッチを取り込む」かを指定するので 指定には 「修正3」 とか一個だけでなく何個でも書け,「修正x:修正y」 のようにコロンで区切って範囲指定もできる。

そして,既に適用したパッチかどうかはチェンジセットIDで確実に 判別してくれるから,リバースパッチなんていうアホな自体に陥ることが ない。すごい,速い,簡単!

cvsやsvnよりずっとイイ!

結局

AとA'を並行で管理して行きたいというときに何が一番いいか、というと

  1. Subversion
  2. CVS
  3. Mercurial

という順番かな。Mercurial の方針としては 「パッチを当てた終わった範囲を人間が考えなくてよい」という メリットを与えて、それで助かる局面もあるが、そのかわり 必ず二つのリポジトリを完全一致させる義務が発生している。 気をつけて import/export を使っていたとしても、 うっかり merge とか、push/pull しようもんならすぐ完全に同一に なってしまう。慣れればそんなうっかりはしないだろうが、 そもそも同一プロジェクトのもの同士で、 patchファイルを生成して当てるなんてことをする必要があるのは頭悪い。 それじゃ、個人個人がローカルにCVSリポジトリを保持して cvs diff したのを送りあうのとちっとも変わらない。

CVSとSubversionはだいたい互角で、じつはある時点に分かりやすい名前で タグを打てて、それがリポジトリ空間を汚さないという意味でCVSのほうが 「区間パッチ取り込み」はやりやすい。この点でsvnは論理タグがないので tags/ ディレクトリにコピーしろーってことになっているが、 個人的にはディレクトリが増えるのがいやだからリビジョン番号だけで 頑張っちゃいがちになって、次に当てるべき区間パッチがどこなのか探すのが たいへん。でも、「異なるブランチの存在はディレクトリの存在」という 思想は A と A' のワーキングディレクトリが同時に存在することに合致するの で気分的にいい。気分的にいい分だけsvnが快適度で勝る。

世の中の流れとしてCVSを酷評するのが流行ってる。確かにCVSのブランチや マージの概念を理解するのは最初は難解で、その流儀に合わせない限りものすご く使いづらい。だが、ブランチと時系列の融合度、たとえ操作対象が 巨大でも、全ての操作を抽象的なタグだけでできるという点でCVSの理念は 美しい。symlink問題とかrename問題というデメリットで乗り換えが必要に なっては来るものの、CVSブランチとタグの概念を引き継ぐものがないのは ちと悲しい。

FreeBSDでもMercurialへの移行を検討しているというけど、 メンテナンス版、リリース版、安定版、開発版と、独立させつつ セキュリティパッチなんかは共有するなんてなモデルに果たして適合できる んだろうか、ちと気になる。

使い方間違ってまっか?

使い方の勉強が足りなかったよ。使い込んで来て,たいてい思いつくことは 拡張モジュールとして用意されているのが Mercurial ということだ。 もうこれで迷いはない。処理速度も圧倒的に速い ことだし。


叱咤激励感想ツッコミはゲストブック

Generated with mkdiary.rb
yuuji@gentei.org
Fingerprint16 = FF F9 FF CC E0 FE 5C F7 19 97 28 24 EC 5D 39 BA
HIROSE Yuuji - ASTROLOGY / BIKE / EPO / GUEST BOOK / YaTeX [Tweet]