Mercurial/rebase

rebase って何

マージの一種。ブランチの途中(大体根本)を切り取って別ブランチの先にくっつけるという操作。 つまり並走しているリビジョン群の片方をどちらかの頭にくっつけて一直線のリビジョンにする。

何が嬉しいの?

複数人開発をしていてpullした時に自分がローカルで操作しているブランチに変更があると Hg が勝手にブランチを分けてしまう。 確かに自分が積み重ねているリビジョンとは違う積み重ねがpullで外部から来るわけだから別ブランチになってしまうのは当然。

ブランチが同一だったとしても変更範囲が被らなければ・・・単に自分の変更をブランチ統合するためだけにマージという行為をしてしまう。 これはソースの状態によるマージではなく単なる変更の順番を解決できないというだけだ。

ということで pull, push をやっているとその度にやる必要のないマージ行為が増えてしまう。 ソース上に問題は無いのに管理上の関係でブランチの分岐と統合がひっきりなしに起きてしまう。

後から見ると、理由があって作っているブランチとこの理由のないブランチがゴチャゴチャになってわけわからなくなるので、一直線にしてわかりやすくしましょうという話。

rebase 拡張によるrebase

絶対に rebase 時にぶつからないとわかっているなら、これが一番お手軽。

拡張をON

Hgは標準でrebaseをサポートしていないがrebase拡張が同梱されているので単にONにすれば使えるようになる

[extensions]
rebase =

コマンド

$ hg rebase -s 移動対象のリビジョン -d 移動先のリビジョン

わかりにくいがsで切り取って先頭に繋げたいリビジョンの塊の根っこのリビジョンを指定する。 dで指定している方の先にsで指定したリビジョンの塊が繋がる。

ということになっているが、実際問題として rebase は本線の変更の取り込みにたいして仕掛り中のブランチの追従させることがメインなので

作業中の hoge ブランチを取り込んで伸びた本線の piyo ブランチの先にくっつける場合このようになる

$ hg update hoge
$ hg rebase -d piyo --keepbranches

このコマンドでは push 済みの branch はrebase で移動できないので hg push –new-branch で押し込む前のものを使う

rebaseのロールバック

なんかできない。

色々なrebase

通常よく使う根本→先頭指定のrebase

普通に切り取られてrebaseされる

途中→先頭指定のrebase

途中から先のリビジョンが先頭に移動する。

するのだが、その「途中」というやつがそれ以前のリビジョンに依存性があった場合、rebaseが失敗するので手動で解決しなければならなくなる。

ソースコード上衝突有りのrebase

rebase拡張の内部処理はよくわかっていないのだが、動きを見ると、 移動先の頭にリビジョンを作ってそこに根本から1個1個マージしているように見える。

なので衝突があったら衝突があったリビジョンを移動する度にマージ処理が入る。 Hg側で解決してくれるのならそのまま続行、駄目なら手動マージということになる。

別ブランチを含むブランチをrebase

どうなる?

普通に接木するように含んでいる別ブランチごと丸々rebaseされる。 注意としては含んでいる別ブランチが名前付きブランチだった場合そのブランチ名が統合先のブランチ名と同じになってしまうということ

graftを使ったrebase

graftはマージアルゴリズムを使って対象のリビジョンを移植する作業なので、並走するワークに対してrebaseしたいブランチの根本から順番にgraftしていけば移植先のブランチの先頭にrebaseしたいブランチをつなげることができる。

graftは移植なので元のブランチが残ってしまう。全部性格に移植が終わったなら、MQ拡張のstripで元を消してしまうとOK。

MQ拡張によるパッチキュー操作によるrebase

rebaseしたブランチ全体をqimportでパッチ化し、パッチとしてMQ側で確保した状態でqpopで履歴改変、リビジョンを削除してしまう。

Hg側で移植先にupdateしてqpushでリビジョンを付与してやる。

バージョン

2012-04-27 新規

タグ

vcs/hg/rebase.txt · 最終更新: 2017-10-10 10:50 by ore