mercurialでpush済みの名前付きブランチをリネームする三つの方法


2011年 03月 26日

mercurialでは一度おこなったコミットは基本的には取り消せません。ブランチを作成するためにもコミットが必要なため、gitのようにカジュアルにブランチのリネームを行う事ができません。ここではそんな中でも何とかブランチをリネームするための3つの方法を紹介したいと思います。

紹介する方法

  • リネームしたいブランチの途中でブランチを切る。
  • リネーム後のブランチを作成し、リネームしたいブランチをマージする。
  • リネーム後のブランチを作成し、リネームしたいブランチをtransplantする。

リポジトリの例

次の様なリポジトリで考えていきます。bad-name-branchをadd-hginoreに変更したいです。

@  changeset:   4:a1b706bc0a8e
|  branch:      bad-name-branch
|  tag:         tip
|  summary:     ignore log directory
|
o  changeset:   3:3751ced37bfb
|  branch:      bad-name-branch
|  summary:     add .hgignore
|
o  changeset:   2:5a66c314fcce
|  branch:      bad-name-branch
|  summary:     start bad-name-branch
|
| o  changeset:   1:3bbfed3d74fa
|/   summary:     fix Makefile
|
o  changeset:   0:f7a29636ef8a
   summary:     initial import

1. リネームしたいブランチの途中でブランチを切る。

一番簡単な方法です。リネームしたいブランチでリネーム後のブランチを作成します。

hg update bad-name-branch
hg branch add-hgignore
hg commit -m "rename from bad-name-branch to add-hgignore"

以前のブランチは閉鎖しましょう。

hg update bad-name-branch
hg commit --close-branch -m "renamed."

結果です。

@  changeset:   6:6290466e4245
|  branch:      bad-name-branch
|  tag:         tip
|  summary:     renamed.
|
| o  changeset:   5:5158665d3618
|/   branch:      add-hgignore
|    summary:     rename from bad-name-branch to add-hgignore
|
o  changeset:   4:a1b706bc0a8e
|  branch:      bad-name-branch
|  summary:     ignore log directory
|
o  changeset:   3:3751ced37bfb
|  branch:      bad-name-branch
|  summary:     add .hgignore
|
o  changeset:   2:5a66c314fcce
|  branch:      bad-name-branch
|  summary:     start bad-name-branch
|
| o  changeset:   1:3bbfed3d74fa
|/   summary:     fix Makefile
|
o  changeset:   0:f7a29636ef8a
   summary:     initial import

利点

おてがる

欠点

変更はリネーム前のブランチに対して行ったことになるので、hg log -b [リネーム後のブランチ]を実行しても、変更を表示する事ができません。

% hg log -b add-hgignore
changeset:   5:5158665d3618
branch:      add-hgignore
summary:     rename from bad-name-branch to add-hgignore

でもhg log -r :[リネーム後のブランチ]で追えます。(kana1より)

% hg log -r :add-hgignore
changeset:   0:f7a29636ef8a
summary:     initial import

changeset:   1:3bbfed3d74fa
summary:     fix Makefile

changeset:   2:5a66c314fcce
branch:      bad-name-branch
summary:     start bad-name-branch

changeset:   3:3751ced37bfb
branch:      bad-name-branch
summary:     add .hgignore

changeset:   4:a1b706bc0a8e
branch:      bad-name-branch
summary:     ignore log directory

changeset:   5:5158665d3618
branch:      add-hgignore
summary:     rename from bad-name-branch to add-hgignore

2. リネーム後のブランチを作成し、リネームしたいブランチをマージする。

1.では変更点が表示できませんでしたが、マージを行う事によってその問題点は克服できます。たいていの場合、方法で問題無いでしょう。

hg update 0
hg branch add-hgignore
hg ci -m "start add-hgignore"
hg merge bad-name-branch
hg commit -m "merge bad-name-branch"

以前のブランチは閉鎖しましょう。

hg update bad-name-branch
hg commit --close-branch -m "merged."

結果です。

@  changeset:   7:ead0b9a097ea
|  branch:      bad-name-branch
|  tag:         tip
|  summary:     merged.
|
| o  changeset:   6:5e1f4f84855a
|/|  branch:      add-hgignore
| |  summary:     merge bad-name-branch
| |
| o  changeset:   5:7ce6dc4afac0
| |  branch:      add-hgignore
| |  summary:     start add-hgignore
| |
o |  changeset:   4:a1b706bc0a8e
| |  branch:      bad-name-branch
| |  summary:     ignore log directory
| |
o |  changeset:   3:3751ced37bfb
| |  branch:      bad-name-branch
| |  summary:     add .hgignore
| |
o |  changeset:   2:5a66c314fcce
|/   branch:      bad-name-branch
|    summary:     start bad-name-branch
|
| o  changeset:   1:3bbfed3d74fa
|/   summary:     fix Makefile
|
o  changeset:   0:f7a29636ef8a
   summary:     initial import

利点

hg log -b [リネーム後のブランチ] で変更点が表示できます。

% hg log -b add-hgignore
changeset:   6:5e1f4f84855a
branch:      add-hgignore
summary:     merge bad-name-branch

changeset:   5:7ce6dc4afac0
branch:      add-hgignore
summary:     start add-hgignore

欠点

リネーム前のブランチの修正を複数のコミットに分けていたとしても、hg log -b [リネーム後のブランチ]で表示される変更はマージ時のものです。個別の変更点を追う事ができません。
hg log -r :[リネーム後のブランチ]で追えます。(kana1より)

3. リネーム後のブランチを作成し、リネームしたいブランチをtransplantする。

どうしてもhg log -b [ブランチ名]で個別の変更点を追いかけたい場合は、transplantを利用するとよいでしょう。transplantにはおあつらえ向きのオプション–branchと–allが存在します。

hg update 0
hg branch add-hgignore
hg ci -m "start add-hgignore"
hg transplant -b bad-name-branch --all

今回の場合ではhg transplant -b bad-name-branch –allは次の様になります。

% hg transplant -b bad-name-branch --all
applying 5a66c314fcce
5a66c314fccec71d9f11140279252c3d23a8b3a5: empty changesetapplying 3751ced37bfb
3751ced37bfb transplanted to ade9fb2b9b37
applying a1b706bc0a8e
a1b706bc0a8e transplanted to 4d760762168c
%

以前のブランチは閉鎖しましょう。

hg update bad-name-branch
hg commit --close-branch -m "transplanted."

結果です。

@  changeset:   8:fb1d2ee9849b
|  branch:      bad-name-branch
|  tag:         tip
|  summary:     transplanted.
|
| o  changeset:   7:4d760762168c
| |  branch:      add-hgignore
| |  summary:     ignore log directory
| |
| o  changeset:   6:ade9fb2b9b37
| |  branch:      add-hgignore
| |  summary:     add .hgignore
| |
| o  changeset:   5:f033147fbfda
| |  branch:      add-hgignore
| |  summary:     start add-hgignore
| |
o |  changeset:   4:a1b706bc0a8e
| |  branch:      bad-name-branch
| |  summary:     ignore log directory
| |
o |  changeset:   3:3751ced37bfb
| |  branch:      bad-name-branch
| |  summary:     add .hgignore
| |
o |  changeset:   2:5a66c314fcce
|/   branch:      bad-name-branch
|    summary:     start bad-name-branch
|
| o  changeset:   1:3bbfed3d74fa
|/   summary:     fix Makefile
|
o  changeset:   0:f7a29636ef8a
   summary:     initial import

利点

hg log -b [リネーム後のブランチ] で全ての変更点が表示できます。

% hg log -b add-hgignore
changeset:   7:4d760762168c
branch:      add-hgignore
summary:     ignore log directory

changeset:   6:ade9fb2b9b37
branch:      add-hgignore
summary:     add .hgignore

changeset:   5:f033147fbfda
branch:      add-hgignore
summary:     start add-hgignore

欠点

リネーム前のブランチを閉じる事を忘れなければ、transplantの操作はブランチを作り直す事と等価なため、中央のリポジトリのチェンジセットが増える以外の欠点はないと考えています。