2013-05-27 17 views
32

私の状況を説明しましょう:Git:リベースブランチを引き出す

Mr BlondとMr Orangeは、コミットM1でマスターブランチから分岐するブランチAで作業しています。ブランチAには、A1とA2の2つのコミットがあります。

M1 
    \ 
    \ 
    A1 - A2 

一方、オレンジ氏はコミットして、M2とM3のマスターブランチにコミットしました。

M1 - M2 - M3 
    \ 
    \ 
    A1 - A2 

氏ブロンドは、リモートから引っ張ると、しばらく後にmasterブランチ上にリベースすることを決定した:

M1 - M2 - M3 
    \   \ 
    \   \ 
    A1 - A2 A1` - A2` 

今A1`とA2`氏ブロンドのでローカルに存在してリベースコミットしています、 A1およびA2は遠隔に存在する。 Blond氏は彼のコミットを押して、-fを使って、彼の変更と "書き換え"の履歴を強制します。これでリモートリポジトリは次のようになります。

M1 - M2 - M3 
      \ 
       \ 
       A1` - A2` 

しかし、オレンジさんはAブランチでも働いていました。彼のローカルリポジトリは次のようになります。

M1 - M2 - M3 
    \ 
    \ 
    A1 - A2 

リモートリポジトリのAブランチと同期させるためにオレンジ氏は何をする必要がありますか?

通常のプルは機能しません。 pull -fローカルからのリモートからの変更を強制しますか?私は、Aのローカルバージョンを削除し、リモートリポジトリから再度それを持ってくることは、トリックを行うが、それはそれを達成する良い方法ではないように思う。氏はオレンジが彼の変更を失うこと気にしない場合は

答えて

21

私のオススメ度(または「オレンジ氏の場合はどうしたらよいか」)は、git fetchで始まります。今、私はレポの中でこれを持っていきます。これは、ブロンドがリベースした後で、 "git push -f"を実行する直前のものです。

M1 - M2 - M3 
    \   \ 
    \   \ 
    A1 - A2 A1' - A2' 

一つの重要な違いは、私は私のA2を吹けを指しローカルラベルA、およびリモートラベルremotes/origin/AはA2' を指している必要があります、です(ミスターブロンドは、ローカルラベルAが指して、それを他の方法で回避していましたA2 'およびremotes/origin/A)。

私は「」私が代わりにこれを持っているだろうという名前の枝の私のコピーで作業してきた場合:私の地元のラベルがA3よりもむしろA2を指していると(

M1 ---- M2 ---- M3 
    \    \ 
    \    \ 
    A1 - A2 - A3 A1' - A2' 

;またはA4またはA5私が適用した変更の数に応じて、)今私がしなければならないのは、私のA3(そして、必要であればA4など)をA2 'にリベースすることだけです。 1つの明白な直接的な方法:その後、

$ git branch -a 
    master 
* A 
    remotes/origin/master 
    remotes/origin/A 
$ git branch new_A remotes/origin/A 
$ git rebase -i new_A 

と修正のものがA1' とA2' としてnew_Aにあるので、完全に回転数A1とA2をドロップします。または:

$ git checkout -b new_A remotes/origin/A 
$ git format-patch -k --stdout A3..A | git am -3 -k 

git am -3 -k方法はgit-format-patchマニュアルページに記述されています)。

これらの私は彼が彼のrebase、すなわちをした前に、ミスターブロンドは、第二のアプローチが成功した場合は私が終わる

などA1、A2、A3を、識別し、しなかったことを持っているものを考え出す必要とします:

M1 ---- M2 ---- M3 
    \    \ 
    \    \ 
    A1 - A2 - A3 A1' - A2' - A3' 

私のブランチ名A3' へnew_Aポイントは(私の既存Aブランチはまだ古いA3を指します)。私が最初のアプローチを使って成功すると、同じことが起こります。既存のブランチ名AがA3 'を指すようになりました(そして、A1-A2-A3の古いブランチの名前はありません。私のレポにはまだありますが、それを見つけるにはreflogなどが必要です)。

(私のA3はもちろん、インタラクティブなリベースと 『gitの午前、』法の両方が私が作業が必要になります、A3' になるために修正が必要な場合。)

もちろんそれはちょうどgit merge(なども可能ですゲイリーFixlerによって答えで)、それは与え、下記の番号なし、と(「M」)コミットと可視回転数A1とA2を保つマージを作成します。あなたは、元のA1を保持したい場合は

M1 ---- M2 ---- M3 
    \    \ 
    \    \ 
    A1 - A2 - A3 A1' - A2' -- M 
       \_______________/ 

をそしてA2、これは良いことです。あなたがそれらを取り除きたいのであれば、それは悪いことです。だから、 "何をするか"は、 "結果が欲しいもの"に依存します。

編集する追加:私はすべてが良いことを確認しながら私の古いAブランチの名前を残すように、より良いフォーマット - パッチ方法が好きです。

$ git branch -m A old_A 
$ git branch -m new_A A 

とold_Aを完全に放棄することができれば、その後、::すべての作品、それを仮定して良いですが、ここでは最後の数歩だ

$ git branch -D old_A 

または、同等に、削除支店で始まるが、

30

、彼は彼の地元A2ブランチに取得するには、その後、サーバからgit checkout A2を取得することができ、その後、彼のA2にリセットするにはgit reset --hard origin/A2(リモコンを想定し、「起源」と命名されました)どこのリモコンのA2です。

もし彼が変更を失うのであれば、サーバの変更をマージして解決することができます(彼自身のA2ブランチから、リモートの名前が "origin"であると再度​​仮定して)git merge origin/A2です。これにより、彼とリモコンの両方の上にある新しいコミットが行われ、両者の変更が一緒にマージされます()。これをリモートにプッシュバックすることができます。

+1

注:その後、(new_A枝上に、A3などをリベースの目的のために、またgit rebase --ontoマニュアルを参照してください。編集)A.

にnew_Aの名前を変更します。 '--'と' hard'の間に空白はありません。答えは正確にそれらの2つの間でラップされていたので、しばらく時間がかかりました:) – qbolec

関連する問題