MercurialとGitのブランチの違い

MercurialのブランチというのがどういうものでしかもそれがGitと同じなのかどうかもいままでよくわからなかった。

その辺のモヤモヤがこれを読んで理解できた(気がする)。

experimentalworks » Blog Archive » Mercurial bookmarks
A Guide to Branching in Mercurial / Steve Losh

まずMercurialでは以下の4種類のブランチがある。

  • リポジトリをcloneしてつくるブランチ
  • hg bookmarkで作るブランチ
  • hg branchで作る名前付きブランチ
  • 名無しブランチ

リポジトリをcloneしてつくるブランチは

hg clone test-project test-project-feature-branch

というように単純にcloneして新機能を開発してあとでマージなりリベースなりする。わかりやすい反面ディスク食うよね。

hg bookmarkで作るブランチはGitのブランチに近くて要するにチェンジセットへのポインタです。

hg bookmark new-feature

後述する名前付きブランチとは異なり削除することができます。

ちなみにbookmarks拡張機能なので標準では使えません。

設定方法は以下参照
HgでBookmarksを使う - 負けないように頑張る日記

hg branchで作る名前付きブランチ

hg branch new-feature

はbookmarksと異なり削除することはできません。
Mercurialではhg branchで作ったブランチ名はチェンジセットごとに記録されているので削除できないようです。
Gitのブランチはチェンジセットへのポインタなので削除できるということのようです。

そのかわり

hg ci --close-branch -m "close"

とすればブランチを閉じることができます。
閉じれば

hg branches

で一覧表示されません。
おそらくリリースブランチのように寿命が長いブランチに対しては名前付きブランチを使い、寿命の短いトピックブランチはbookmarksを使うといいんじゃないかと思います。

この辺も参考
hg and git - いろいろ

名無しブランチについてはこの辺参照
Mercurial 勉強中 (4) - branch と heads - daily dayflower

ユースケースはこんな感じらしい。

つまりコミットログがこんな感じになっていて

o  チェンジセット:   2:f8bd3f259746
|  ユーザ:           wyukawa
|  日付:             Sun Dec 05 20:03:18 2010 +0900
|  要約:             add feature B
|
o  チェンジセット:   1:d2e687375646
|  ユーザ:           wyukawa
|  日付:             Sun Dec 05 20:02:59 2010 +0900
|  要約:             add feature A
|
o  チェンジセット:   0:4a3fa8b5db70
   ユーザ:           wyukawa
   日付:             Sun Dec 05 20:02:44 2010 +0900
   要約:             initial import

なんかバグを見つけたのでチェンジセット3で修正してこんな感じになりました。

@  チェンジセット:   3:c1651bbd03da
|  タグ:             tip
|  ユーザ:           wyukawa
|  日付:             Sun Dec 05 20:05:12 2010 +0900
|  要約:             fix bug
|
o  チェンジセット:   2:f8bd3f259746
|  ユーザ:           wyukawa
|  日付:             Sun Dec 05 20:03:18 2010 +0900
|  要約:             add feature B
|
o  チェンジセット:   1:d2e687375646
|  ユーザ:           wyukawa
|  日付:             Sun Dec 05 20:02:59 2010 +0900
|  要約:             add feature A
|
o  チェンジセット:   0:4a3fa8b5db70
   ユーザ:           wyukawa
   日付:             Sun Dec 05 20:02:44 2010 +0900
   要約:             initial import

でもバグ修正前に再現するテストケース書いた方がいいよなってことで、チェンジセット2に戻って失敗するテストコードを追加します。

hg update -r 2
... add test
hg ci -m "add test"

そうするとこんな感じになります。Multiple HeadsというMercurial特有の状態になります。で、これをマージなりリベースなりするというわけです。

チェンジセット1,2,3の線が名無しブランチです。
ちなみにこれはhg glogの結果です。GraphlogExtension - Mercurialという拡張を使います。

@  チェンジセット:   4:30f6f0631afd
|  タグ:             tip
|  親:               2:f8bd3f259746
|  ユーザ:           wyukawa
|  日付:             Sun Dec 05 20:11:00 2010 +0900
|  要約:             add test
|
| o  チェンジセット:   3:c1651bbd03da
|/   ユーザ:           wyukawa
|    日付:             Sun Dec 05 20:05:12 2010 +0900
|    要約:             fix bug
|
o  チェンジセット:   2:f8bd3f259746
|  ユーザ:           wyukawa
|  日付:             Sun Dec 05 20:03:18 2010 +0900
|  要約:             add feature B
|
o  チェンジセット:   1:d2e687375646
|  ユーザ:           wyukawa
|  日付:             Sun Dec 05 20:02:59 2010 +0900
|  要約:             add feature A
|
o  チェンジセット:   0:4a3fa8b5db70
   ユーザ:           wyukawa
   日付:             Sun Dec 05 20:02:44 2010 +0900
   要約:             initial import

Gitの場合はチェンジセット3までいったらブランチ作ってgit resetでチェンジセット2に戻ってテスト作る感じでしょう。
その場合git logはHEADからたどれるコミットを拾っていくのでチェンジセット3のログはgit reflogからじゃないと見れません。

こうしてみていくとMercurialとGitは結構違いますね。