Hg:gitのリベースのようなリベースを行う方法


207

Gitではこれを行うことができます:

1.新しい機能の作業を開始します。
$ git co -b newfeature-123#(ローカル機能開発ブランチ)
いくつかのコミットを行う(M、N、O)

マスターA --- B --- C
                \
newfeature-123 M --- N --- O

2.アップストリームマスターから新しい変更をプルします。
$ git pull
(ff-commitsで更新されたマスター)

マスターA --- B --- C --- D --- E --- F
                \
newfeature-123 M --- N --- O

3.マスターをリベースして、私の新機能を 
最新の上流の変更に対して開発することができます:
(newfeature-123から)
$ git rebase master

マスターA --- B --- C --- D --- E --- F
                            \
newfeature-123 M --- N --- O


Mercurialで同じことをする方法を知りたいのですが、Webを調べて答えを探しましたが、私が見つけた最善の方法はgit rebaseです。

そのリンクは2つの例を提供します:
1.私はこれを認めます:(例のリビジョンを自分の例のリビジョンで置き換えます)

hg up -CF  
hgブランチ-f newfeature-123  
hg移植-a -b newfeature-123 

リベース前のMNOをマージされていないヘッドとして残し、更新されたメインラインから分岐することを表す3つの新しいコミットM '、N'、O 'を作成することを除いて、それほど悪くはありません。

基本的に問題は私がこれで終わることです:

マスターA --- B --- C --- D --- E --- F
                \ \
newfeature-123 \ M '--- N' --- O '
                  \
newfeature-123 M --- N --- O

削除する必要があるローカルの不要なコミットが残るため、これは適切ではありません。

  1. 同じリンクからの他のオプションは
hg qimport -r M:O
hg qpop -a
hg up F
hgブランチnewfeature-123
hg qpush -a
hg qdel -r qbase:qtip

そしてこれは望ましいグラフになります:

マスターA --- B --- C --- D --- E --- F
                            \
newfeature-123 M --- N --- O

しかし、これらのコマンド(6つすべて!)は、

$ git rebase master

これがHgで唯一の同等のものか、Gitのような単純な他の方法が利用できるかどうかを知りたいです。


7
「これは、削除する必要のあるローカルの不要なコミットを残すため、良くありません。」-実際には、gitは同じことを行います。元のブランチのコミットを変更または削除するのではなく、マスターの上に同じ変更セットを適用する新しいコミットを作成するだけです。あなたはまだ使用して古いものにアクセスすることができ、git reflogそれらがガベージコレクションを取得するまで、それらは完全に消えていません。reflogを使用する必要がないように、それらを名前付きブランチに保持したい場合は、リベースのgit branch feature-123_original前に行ってください。
MatrixFrog

5
ランダムな質問:チェンジセット/ブランチを自分でASCIIで描画しましたか、それを行うツールはありますか?
アミールラチャム

2
TextWranglerを "overwrite"に設定して、自分で行っただけです。
jpswain

回答:


235

VonCはあなたが探しいる答えであるRebase Extension 持っています。ただし、me​​rcurialではデフォルトでmqもrebaseも有効になっていない理由について少し考えてみる価値があります。私があなたが説明している方法で作業するとき、これはほぼ毎日ですが、これが私が取るパターンです:

1. Start working on a new feature:
$ hg clone mainline-repo newfeature-123
do a few commits (M, N, O)

master A---B---C
                \
newfeature-123   M---N---O

2. Pull new changes from upstream mainline:
$ hg pull

master A---B---C---D---E---F
                \
newfeature-123   M---N---O

3. merge master into my clone so that my new feature 
can be developed against the latest upstream changes:
(from newfeature-123)
$ hg merge F

master A---B---C---D---E---F
                \           \
newfeature-123   M---N---O---P

必要なのはそれだけです。最終的にはnewfeature-123クローンになり、満足したらメインラインに簡単に戻すことができます。最も重要なのは、しかし、私は歴史を変えたことはありません。誰かが私のcsetを見て、それらが元々何に対してコーディングされていたか、そして作業中のメインラインの変更にどのように反応したかを見ることができます。誰もがそれが価値があると思うわけではありませんが、私たちが望んでいたことが起こったのではなく、実際に起こったことを示すのはソース管理の仕事であると私は確信しています-すべての行き止まりとすべてのリファクタリングは消えない痕跡を残し、リベースする必要がありますそして他の履歴編集技術はそれを隠します。

soapboxを片付けている間、VonCの答えを選んでください。:)


18
注:もちろん、Gitでは正確に履歴を書き換えることはできません。新しい履歴を簡単に作成するためだけです(utcc.utoronto.ca/~cks/space/blog/tech/GitNewHistory)。RebaseExtensionを追加することにより、Mercurialは同じ便利な方法で古い履歴を新しい履歴に置き換えることができます。どうして?マージが常に正しい答えであるとは限らないため、特にチェンジセットをFの上に進化として表示する必要があり、逆(PがOの上にマージされる)ではない場合
VonC

19
VonC、私は同意します。マージが常に正しい選択であるとは限りませんが、違いは、VCSの履歴で通知できるようにしたいものだと思います。歴史はいつでも「最初は統合しようとしてうまくいかなかったし、当時は役に立たないと思った」という質問に答えられるべきだと思います。科学者はページに番号を付けたペンでログブックを保管し、AFAICソフトウェアエンジニアはこれまでに入力したすべてのバイトを保存する必要があります。履歴の書き換え、csetの親子関係でさえ、CollapseExtension、HistEditなどは確かに違反します。それは完全に個人的な選択の問題です。
Ry4an Brase 2010

14
個人的な選択の場合は+1。その結果、Gitでは、些細な分岐にはrebaseを使用し、重要な分岐にはマージを使用します。これにより、私が重要だと思う場所でマージ履歴を保存できますが、ほとんどの場合、ログをクリーンで線形に保つことができます。
コス

16
また、最初に多数の小さなコミットを実行してから、それらを結合、ラベル付け、クリーンアップし、それらをメインブランチとマージする(またはメインブランチの上にリベースする)ため、インタラクティブなリベースも大量に行います。変更のコーディングと管理を別々のステップにするのが好きです。
Kos

6
「開発パスに沿ってすべてのバイトを保存する」という哲学は、貢献者が一連のパッチを提案し、メンテナからのフィードバックに基づいて修正するという大規模なオープンソースプロジェクトにはあまり適していません。その後、最終的にメインプロジェクトリポジトリには、すべての変更の適切なバージョンのみが含まれ、関連するすべての変更が1回のコミットで行われます。git Interactive rebaseは、作業中の変更を一連のコミットにクリーンアップしてツリーを壊さないようにするのに非常に役立ち、コミットメッセージには、すべての作業が完了した後に何を言うかを反映するコミットメッセージが含まれます。
Peter Cordes 2014

104

Rebase Extensionを探しているかもしれません。(SummerOfCode 2008の一部として実装)

このような場合、ローカルの変更を「切り離して」、リポジトリをメインストリームと同期させてから、新しいリモートの変更の上にプライベートな変更を追加すると便利です。この操作はリベースと呼ばれます。

からの行き方

代替テキスト

に:

代替テキスト


以下のコメントsteprobe

変更をプルしておらず、リポジトリに2つのブランチがある場合、次のようにできます(を使用keepbranches)。

hg up newfeature-123 
hg rebase -d master --keepbranches

--keepbranches:元のブランチ名を継承します。)

Mojcaは次のように述べています。

私はを使うのhg rebase --source {L1's-sha} --dest {R2's-sha}が好きですが--keepbranches、最後に追加できることを知りませんでした。

以下に例示することにより、ジョナサン・ブラックバーン

 hg rebase -d default --keepbranches

1
Rebase Extensionを確認しましたが、それでもわかりません。上記で説明したことを行うための手順を説明していただけますか?
jpswain 2010

6
あなたが変更を引っ張っていない、とあなたはあなたのレポに2つの支店を持っている場合は、あなたが行うことができますhg up newfeature-123が続くhg rebase -d master --keepbranches
steprobe

2
私はリベースに問題はないと信じています。それは単なる選択の問題です。問題は、リベースが悪用され、@ Ry4anで履歴を書き換えないことです。これにより、何がいつ発生するかを知ることができます。
ホルヘバルガス、2011

@steprobe:--keepbranchesを使用するためのヒントをありがとうございます。私はを使うのhg rebase --source {L1's-sha} --dest {R2's-sha}が好きですが--keepbranches、最後に追加できることを知りませんでした。これは他の下位の回答で言及されていますが、この回答にも明示的に書き込んでおくとよいでしょう。
Mojca

@Mojca問題ありません。私はそれに応じて答えを編集しました。
VonC、

44

最新のHgインストールがあると仮定すると、単純に以下を追加できます。

[extensions]
rebase = 

〜/ .hgrcに。

その後、コマンドを使用することができhg rebasehg pull --rebaseまたはhg help rebase


2
:ちょうどその時あなたが実行する必要があるだろうに、用語コマンドのこのに追加する hg rebase -s o -d f
シンプルソリューション

21

上記の答えがOPの目標(タスクブランチを維持し、親ブランチの後のポイントに基づいてリベースする)を達成したとは思いません。

このグラフ(graphlog拡張を使用して生成されたものです。graphlogに対するマニアックな愛情)から始めましょう。

@  9a4c0eb66429 Feature 3 commit 2 tip feature3
|
| o  af630ccb4a80 default againagainagain  
| |
o |  98bdde5d2185 Feature 3 branch commit 1  feature3
|/
o  e9f850ac41da foo   

私がfeature3ブランチを使用していて、againagagainコミットからそれをリベースしたい場合は、実行すると理解していますhg rebase -d default。これにより、次の結果が得られます。

@  89dada24591e Feature 3 commit 2 tip 
|
o  77dcce88786d Feature 3 branch commit 1  
|
o  af630ccb4a80 default againagainagain  
|
o  e9f850ac41da foo  

任務完了?そうは思いません。問題は、feature3ブランチでのコミットが再び再びベースにされたときに、feature3ブランチが削除されたことです。私のコミットはデフォルトのブランチに移動されました。これは私が最初に回避しようとしていたものです。

Gitでは、結果は次のようになります。

@  9a4c0eb66429 Feature 3 commit 2 tip
|
o  98bdde5d2185 Feature 3 branch commit 1 **feature3**
|
o  af630ccb4a80 default againagainagain
|
o  e9f850ac41da foo

feature3ブランチがまだ存在し、2つのコミットがまだfeature3ブランチにあり、デフォルトでは表示されないことに注意してください。タスクブランチを保持しないと、これがマージと機能的にどのように異なるのかわかりません。

更新:私は発見した--keepbranches hg rebaseでサポートさフラグ。すべてがokey-dokeyであることを報告させていただきます。を使用してhg rebase -d default --keepbranches、私が切望したGitの動作を正確に再現します。後でいくつかのエイリアスがあり、私は誰の仕事のようにリベースしています。


7
リベースで--keepbranchesフラグを発見しました。問題が解決しました。これが私のコードだったら、それをデフォルトにしますが、それは私だけです。
ジョナサンブラックバーン

1
上記の回答に少しだけ情報を追加すると便利だと思います。見つけるのに少し時間がかかりました。
HansMari 2013

3

一部の人々はすべてのイテレーションをすべて維持するのが良いと思っていると言ってきたので、大規模なオープンソースプロジェクトの場合、マージと開発のイテレーションでいっぱいの変更を受け入れると、面倒なメインラインの改訂履歴が作成され、現在のバージョンがどのようにそこに到達したかを確認するのにあまり役に立たない改訂履歴。

これは、送信された変更が受け入れられないうちに、それらを記述していない人々によってレビューされたときにうまく機能するため、メインラインに送られる変更は、通常、デバッグされて機能します。次に、ラインの原点に戻ると、それに伴う変更のすべてが表示されます。変更が発生している途中の途中ではありません。

x265の貢献者のページには、説明の提出のためにそれらを準備するために、あなたが取り組んでいる一連の変更を再コミットする方法 x265プロジェクトへ。(Git guiのステージ用/ステージ解除用の差分ハンクのコミットのように、TortoiseHGを使用して個々のファイルのすべてではなく一部の変更をコミットすることを含みます)。

このプロセスでは、hgを上流のヒントに更新し、すべての変更を作業ディレクトリでコミットせずに取得します。あなたが提出したいものの一部ではないものを棚上げし、素敵なコミットメッセージで適切な数の個別のコミットに残りを分割してください。

私はあなたが修正しているパッチセットの以前のイテレーションからのコミットメッセージをコピー/貼り付けしてから編集すると思います。または、古いコミット(git言語でのチェリーピック)を移植し、1つずつ修正して、古いコミットメッセージを編集の開始点として取得することもできます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.