Differences between revisions 2 and 3
Revision 2 as of 2012-11-06 15:19:56
Size: 16398
Editor: ntsitm118243
Comment:
Revision 3 as of 2012-11-06 20:30:43
Size: 16398
Editor: ntsitm118243
Comment:
Deletions are marked like this. Additions are marked like this.
Line 47: Line 47:
   中断したベースを再開します。    中断したベースを再開します。
Line 50: Line 50:
   中断したベースを中止します。    中断したベースを中止します。
Line 75: Line 75:
意味的には、引数なしのリベースは、 ''自分が今作業しているブランチを取って、正しい状態にする'' ことであると言えます。言い換えると、手元で行った変更をチェックアウト中の名前つきブランチの最新HEAD上に移動することを意味します。 意味的には、引数なしのリベースは、 ''自分が今作業しているブランチを取って、正しい状態にする'' ことであると言えます。言い換えると、手元で行った変更をチェックアウト中の名前つきブランチの最新HEAD上に移動することを意味します。

このページは RebaseExtension の日本語訳です。

Rebase エクステンション

現在、このエクステンションは Mercurial とともに配布されています。 作者: Stefano Tortarolo

設定

設定ファイル(例えば .hg/hgrc)でエクステンションを有効にしてください:

[extensions]
rebase = 

はじめに

プロジェクトに貢献するときに、いくつかのパッチは非公開にしたまま、リポジトリ全体を最新の状態に保ちたい場合があります。

そういう場合には、一度手元の変更を"デタッチ"して、リポジトリをメインストリームと同期したあと、手元の変更をリモートから取得した最新の変更の上に追加するのが有効です。この手順を rebase(リベース) と呼びます。

一般に、このエクステンションを使って、リビジョンをある地点から別の地点に移動することができます。良くあるパターンを、"シナリオ" セクションで説明しています。

機能

  • 単純なリベース、複雑なリベース
  • 中断したリベースの中止
  • 中断したリベースの再開
  • 中断時の変更の検出

使い方

概要

   hg rebase [--source REV | --base REV] [--dest REV] [--collapse] [--detach] [--keep] [--keepbranches] | [--continue] | [--abort]

説明

  • --source rev

    • 指定したリビジョンとその子孫リビジョンがリベース先に移動されます。
  • --base rev

    • 指定したリビジョンとリベース先リビジョンの共通の祖先から、指定したリビジョンおよびその子孫リビジョンが、リベースの対象になります。(共通の祖先自身は除きます)

      --sourceと同時に指定することはできないことに注意してください

  • --dest rev

    • 指定されたリビジョンの上に、リベース対象のリビジョンが移動されます。
  • --continue

    • 中断したリベースを再開します。
  • --abort

    • 中断したリベースを中止します。
  • --collapse

    • リベースされるリビジョンをまとめます。
  • --keep

    • 元のリビジョンをリベース後も残します。
  • --keepbranches

    • 元のブランチ名を引き継ぎます。
  • --detach (Mercurial 1.6以降)

    • リベース対象のリビジョンを強制的に元のブランチから切り離します。

      訳注:このオプションは、現在非推奨です。

pullコマンドとの統合

このエクステンションによって、pullコマンドにオプションが追加されます。

   hg pull --rebase

これを指定すると、もしリベースするべきリビジョンが手元にある場合はプル後にリベースされ、なければhg pull --updateと同様の動作をします。

一般的なケース

このエクステンションを引数なしで実行することができるというのは重要なポイントです。

意味的には、引数なしのリベースは、 自分が今作業しているブランチを取って、正しい状態にする ことであると言えます。言い換えると、手元で行った変更を、チェックアウト中の名前つきブランチの最新HEAD上に移動することを意味します。

次のようなシチュエーションを考えてみましょう。:

L* は、最後にプルしてから手元で行った変更を表しています。

hg pull

メインストリームから、新しいリビジョンを2つプルしました。

たいてい、ここでやりたいのは L* を R2 の上に移動することです。それは、以下のように簡単にできます。:

hg rebase

結果:

Note: 前述の通り, これは hg pull --rebase で1アクションで実行できます。

衝突するマージの扱い

L* における変更が R* における変更と衝突することがあります。その場合、エクステンションは停止し、現在の状態を保存して、ユーザ自身が衝突を解消できるようにします。

リベースが中断したときには、2つの選択肢があります。:

  • 中止
  • 続行

中止

以下のコマンドで、中断されている処理は中止され、リポジトリは元の状態に戻ります。:

$ hg rebase --abort

続行

しかし、中断されている処理を再開する方が一般的です。それは以下のコマンドで出来ます:

$ hg rebase --continue

リベースが出来ない場合

リベースができないシチュエーションがいくつかあります。:

  • リベースポイント(リベース元)がリベース先の祖先の場合
  • リベースポイント(リベース元)がリベース先の子孫の場合

    この場合は、 transplantstrip コマンドを使う必要があります。例えば:

    hg up -r <targetrev>  # Needed because the transplant -m option doesn't work
    hg transplant <source>:tip
    hg strip <source>
  • リベース元(source)がマージリビジョンで、その親がどちらも外部にある場合

MQパッチに関する注意事項

現在の実装では、MQパッチはqfinishされ、リベース後にqimportされます。これによって、exportのようなヘッダがリベースされたパッチに追加されます。例えば、

  • 元のパッチ:
    Description P0
    
    diff --git a/f b/f
    etc...
  • リベース後のパッチ:
    # HG changeset patch
    # User Stefano Tortarolo <stefano.tortarolo@gmail.com>
    # Date 1217929313 -7200
    # Node ID 92bd85e9196feac01fdf2eb2ce7275e9a575a730
    # Parent  6e55161e68b2062d629c05b89b0ea3424eec9a2f
    Description P0
    
    diff --git a/f b/f
    etc...

シナリオ

ここからは、もっと興味深いシナリオを分析していきましょう。

シナリオ A

最初は、もっとも単純なパターンの、シンプルブランチです。

このシナリオでは、2つの興味深い相互作用があります。

トップへのリベース

$ hg up C
$ hg rebase -d E

以下のやり方でも同じ結果になります。:

$ hg up E
$ hg rebase -s C

中間リビジョンへのリベース

$ hg up C
$ hg rebase -d D

シナリオ B

2番目のシナリオには、もっと複雑なパターンが含まれます。このシナリオでは、アップストリームからクローン氏、何度かマージを行っています。

Iの上にDをリベース

  • D はマージリビジョンですが、 H と違って スキップ されません。

Iの上にBをリベース

  • この場合は、2つのリビジョン(D と H)はスキップされます。

Bの上にCをリベース

Iの上にGをリベース

Note: 親がリベース先の祖先の場合に 限り 、リベースによって親との関係が削除されます。 --detach オプションを指定すると、強制的にこの関係を削除します。

シナリオ C

このケースは、リポジトリがひとつだけの(マージされた)HEADを持つという、非常に一般的なシチュエーションを表しています。

Cの上にDをリベース

  • 明らかに、リビジョン F はスキップされています。

集約

複数のチェンジセットを、ひとつだけのリビジョンとして別のブランチにリベースできると便利なこともあります。

これは --collapse を指定すればできます。

Bの上にCを集約してリベース

詳細

親リビジョンとの関係付け

与えられたノード(N) をリベースする際に、その親の状態によってことなる結果になることがあります。

ここからは、 P1NN の一つ目の親、 P2N は二つ目の親を指すものとします。

例えば、 P1'N は、リベースされた N の一つ目の親です。

それらのシチュエーションは、以下の表にまとめられます。:

P2N = A

P2N = S

P2N = E

P2N = N

P1N = A

p1 = P2'N

p1 = target, p2 = P2N

p1 = target

P1N = S

p1 = P1'N

p1 = P1'N, p2 = P2'N

p1 = P1'N, p2 = P2N

p1 = P1'N

P1N = E

p1 = target, p2 = P1N

p1 = P2'N, p2 = P1N

p1 = target, p2 = P1N

A: リベース先の祖先 S: リベース対象内 E: 外部 N: なし

空のセルは、以下の場合にあたります。:

  • P1N = P2N = A は、 N もリベース先の祖先であることを意味しており、これはリベースできないパターンです。

  • P1N = P2N = E は、 N がマージされたリビジョンであり、親のどちらもリベース先の祖先でないことを意味しており、これもリベースできないパターンです。(アイデア: もっといいリビジョン位置を仮定することは可能?) このケースは N がリベースポイントの場合にだけ発生することに注意してください。

以下のことも注意してください:

  • P1N = None の場合、必然的に P2N = None になります。

  • P1N = P2N = None になるのは、 N がルートの場合だけです。(この場合は、ノードを自分の子孫の上にリベースできないというルールにより禁止されます)

コマンドのヘルプ

Mercurial 2.0では、以下がrebaseコマンドの公式なドキュメントです。

    Rebase uses repeated merging to graft changesets from one part of history
    (the source) onto another (the destination). This can be useful for
    linearizing *local* changes relative to a master development tree.

    You should not rebase changesets that have already been shared with
    others. Doing so will force everybody else to perform the same rebase or
    they will end up with duplicated changesets after pulling in your rebased
    changesets.

    If you don't specify a destination changeset ("-d/--dest"), rebase uses
    the tipmost head of the current named branch as the destination. (The
    destination changeset is not modified by rebasing, but new changesets are
    added as its descendants.)

    You can specify which changesets to rebase in two ways: as a "source"
    changeset or as a "base" changeset. Both are shorthand for a topologically
    related set of changesets (the "source branch"). If you specify source
    ("-s/--source"), rebase will rebase that changeset and all of its
    descendants onto dest. If you specify base ("-b/--base"), rebase will
    select ancestors of base back to but not including the common ancestor
    with dest. Thus, "-b" is less precise but more convenient than "-s": you
    can specify any changeset in the source branch, and rebase will select the
    whole branch. If you specify neither "-s" nor "-b", rebase uses the parent
    of the working directory as the base.

    By default, rebase recreates the changesets in the source branch as
    descendants of dest and then destroys the originals. Use "--keep" to
    preserve the original source changesets. Some changesets in the source
    branch (e.g. merges from the destination branch) may be dropped if they no
    longer contribute any change.

    One result of the rules for selecting the destination changeset and source
    branch is that, unlike "merge", rebase will do nothing if you are at the
    latest (tipmost) head of a named branch with two heads. You need to
    explicitly specify source and/or destination (or "update" to the other
    head, if it's the head of the intended source branch).

    If a rebase is interrupted to manually resolve a merge, it can be
    continued with --continue/-c or aborted with --abort/-a.

関連リンク


CategoryBundledExtension

JapaneseRebaseExtension (last edited 2012-11-07 14:41:13 by YuyaNishihara)