hg(Mercurial)のphaseを使ってリモートリポジトリをぐっちゃりさせない

mercurial

push only necessary commits (ignore test commits!)

cloneで持ってきたローカルリポジトリで、「バグ修正作業なんだけど、どこをどうしたらどうなるかわかんないから、トライ&エラーでガシガシだ~」的な時は細かにコミットして行ったり戻ったり、やっぱりさっきのやっておこう、的な迷走がよくある(よくあっちゃダメだろ)のですが、その修正をまるごとリモートリポジトリに反映させると、とても可哀想なリポジトリになります。あみだくじみたいな。

これでは後から作業追いかけるにも、他人の修正を確認するにも大変。リモートリポジトリには必要な修正のコミットだけ反映させて、試行錯誤は反映させないようにしたい!

で、Phaseを使うと都合よく出来そうってことで。
//TODO: 画像(graph)挿入

Phaseで秘密の人になる

PhaseはMercurialの2.1から導入されています。 http://mercurial.selenic.com/wiki/Phases

phaseは以下で確認できます。

$ hg phase -r [リビジョン]

また、phaseコマンドはオプションを付けることで(-s:secret, -d:draft, -p:public), 指定のリビジョンのphaseを変更できます。

$ hg cloneで持って来たリビジョンのphaseはpublicになっています。

さて、試行錯誤だーってことで、適当になにか編集してcommitしちゃいます。するとPhaseがdraftのリビジョンが出来ます。 これは試行錯誤のリビジョンなので他に出したくありません。Phaseをsecretに変えちゃおう。

$ hg phase -s -r . -f
(-fオプション(--force)が必要になります)

これで試行錯誤リビジョンのphaseがsecretになりました。

$ hg phase -r .
>[リビジョン]: secret

もう秘密の人なのでこの状態で$ hg pushしても”secretのチェンジセットは無視するよ”と言われます。やったね!

試行錯誤がんばる

編集して$ hg commitを繰り返して修正が完了するまでがんばる。 phaseがsecretの状態でcommitしているので、子リビジョンもsecretとなるため、このコミット達はpushしても反映されません。

親リビジョン(となって欲しいリビジョン)に最終修正結果を反映させてコミット

がんばったので修正が終わったー。試行錯誤の最終コミットおわり。 さて、リモートリポジトリに最終結果だけを反映させるぞー。ということでpushするコミットを作ろう。

親リビジョンを決め、公の人に戻ります。

$ hg update -r [親リビジョンにしたいリビジョン]

試行錯誤の最終結果を反映します。

$ hg revert -r [試行錯誤の最終コミットのリビジョン] --all

コミットします。phaseがdraftのリビジョンが出来ます。

$ hg commit

状態としては、 試行錯誤方向のリビジョンと、今コミットしたリビジョンでひとつの親から2つでているので、無名ブランチがある状態になってます。hg headでみてみるとHEADが増えています。

$ hg head

リモートリポジトリに反映させる

pushするだけ。

まとめ

(親リビジョン:[REVNUM])
$ hg clone REPO -r [REVNUM]
$ hg commit -m "試行錯誤中1"
$ hg phase -s -r . -f
$ hg commit -m "試行錯誤中2"
$ hg commit -m "試行錯誤中3(修正完了!)"
$ hg update -r [REVNUM]
$ hg revert -r tip --all
$ hg commit -m "修正完了~"
$ hg push

(cloneして、)commitして、秘密の人になって、試行錯誤して、親リビジョンに戻って同時に公の人に戻って、最終結果反映させて、commitして、push!!

(余談)

無名リポジトリの話が途中で出たので、Phaseを使わないで同じようなことをする方法。。

(親リビジョン:[REVNUM])
$ hg clone REPO -r [REVNUM]
$ hg commit -m "もじゃもじゃ"
$ hg update -r [REVNUM]
$ hg commit -m "試行錯誤中1"
$ hg commit -m "試行錯誤中2"
$ hg commit -m "試行錯誤中3(修正完了!)"
$ hg update -r [REVNUM]
$ hg revert -r tip --all
$ hg commit -m "修正完了~"
$ hg push -r .

こんな感じ。

phaseをsecretにして、リモートリポジトリへのpushの対象から外す代わりに、

$ hg update -r [REVNUM]
$ hg commit -m "もじゃもじゃ"
$ hg update -r [REVNUM]
$ hg commit -m "試行錯誤中1"

[REVNUM]のリビジョンから複数の子を出すことで無名ブランチを作り、headを増やすことで、pushした時に”headがアレだぞ!”って怒られることでpushを避けます。試行錯誤の所は同様です。

$ hg push -r .

そして最後にpushする時にリビジョンを指定することで、指定したリビジョンとそのancentorsのみ反映させ、試行錯誤たちを除きます。

リビジョン指定せずにpushすると、”headがアレだぞ!”と怒られるのですが(というかそれを利用してpushから逃れるのがこの方法)、ここでhgのおすすめに従って-fオプション使って反映させようとすると、(当然ながら)試行錯誤含めて全てリモートリポジトリに入っちゃうので注意です。

ちなみに…

“headがアレだぞ!”とは↓のことです

$ hg push
  :
  :
abort: push creates new remote head xxxxxxxxxxxx!
(did you forget to merge? use push -f to force)

gitではどういう方法・手順になるんでしょう?

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

  1. コメントはまだありません。

  1. トラックバックはまだありません。