誰かが公開されているブランチにリベースまたはリセットを押した後、回復/再同期するにはどうすればよいですか?
-
28-09-2019 - |
質問
私たちは皆、公開された作品を決してリベースにしないでください、それが危険であることなどを聞いています。しかし、私はリベースの場合に状況に対処する方法のために投稿されたレシピを見たことがありません は 公開。
さて、リポジトリが既知の(そして好ましくは小さい)グループによってのみクローン化されている場合にのみ、これは本当に実現可能であることに注意してください。フェッチ(!)。
私が見た1つの明らかな解決策は、あなたが地元のコミットを持っていない場合に機能します foo
そして、それは反転します:
git fetch
git checkout foo
git reset --hard origin/foo
これは単に地元の状態を捨てます foo
リモートリポジトリによる歴史を支持しています。
しかし、そのブランチで大幅なローカルな変更を犯した場合、状況にどのように対処しますか?
解決
プッシュされたリベースの後に同期して戻ることは、ほとんどの場合、それほど複雑ではありません。
git checkout foo
git branch old-foo origin/foo # BEFORE fetching!!
git fetch
git rebase --onto origin/foo old-foo foo
git branch -D old-foo
すなわち。最初に、リモートブランチが元々あった場所のブックマークを設定した後、それを使用して、その時点からローカルコミットをrebasedリベースのリモートブランチに再生します。
リベッシングは暴力のようなものです。問題が解決しない場合、もっと必要です。 ☺
もちろん、ブックマークなしでこれを行うことができます。前提条件を調べると origin/foo
IDをコミットし、それを使用します。
これはまた、ブックマークを作るのを忘れた状況に対処する方法でもあります 前 フェッチ。何も失われません - リモートブランチのリフェログを確認するだけです。
git reflog show origin/foo | awk '
PRINT_NEXT==1 { print $1; exit }
/fetch: forced-update/ { PRINT_NEXT=1 }'
これにより、コミットIDが印刷されます origin/foo
その歴史を変えた最新のフェッチの前に指摘されました。
その後、簡単にできます
git rebase --onto origin/foo $コミット foo
他のヒント
私は言います 上流のリベースから回復します Git-Rebase Manページのセクションでは、このほとんどすべてをカバーしています。
それはあなた自身のリベースから回復することと本当に変わりません - あなたは1つの枝を移動し、彼らの歴史の中でそれを新しい位置に持っていたすべての枝を再ゼロにします。
GIT 1.9/2.0 Q1 2014から始めて、書き込みのように、書き直された上流のブランチでそれを再baseする前に、以前の枝の起源をマークする必要はありません アリストテレス・パガルツィス's 答え:
見る コミット07d406b と D96855Fをコミットします :
に取り組んだ後
topic
で作成されたブランチgit checkout -b topic origin/master
, 、リモートトラッキングブランチの歴史origin/master
巻き戻されて再建された可能性があり、この形の歴史につながります。
o---B1
/
---o---o---B2--o---o---o---B (origin/master)
\
B3
\
Derived (topic)
どこ
origin/master
コミットを指すために使用されますB3
,B2
,B1
そして今、それは指し示していますB
, 、 そしてあなたのtopic
ブランチは、その上に戻って開始されましたorigin/master
いたB3
.このモードは、のリフログを使用します
origin/master
見つけるにはB3
フォークポイントとして、topic
更新の上にリベースすることができますorigin/master
に:
$ fork_point=$(git merge-base --fork-point origin/master topic)
$ git rebase --onto origin/master $fork_point topic
それが理由です git merge-base
コマンドには新しいオプションがあります。
--fork-point::
ブランチ(またはにつながる歴史があるポイントを見つけます
<commit>
)別のブランチ(または任意の参照)からフォークされた<ref>
.
これは、2つのコミットの共通の祖先を探すだけでなく、 また、反射物を考慮しています<ref>
歴史が至るかどうかを確認します<commit>
ブランチの以前の化身からフォーク<ref>
.
"
git pull --rebase
「コマンドは、ブランチのフォークポイントを計算します。base
「支店(通常、リモートトラッキングブランチ)ブランチの作業は、「ベース」ブランチが巻き戻され、再建された場合に対処するために基づいていました。
たとえば、歴史がどこにあるかのように見えた場合:
- 現在のヒント」
base
「ブランチがありますB
, 、しかし、以前のフェッチは、その先端が以前だったことを観察しましたB3
その後B2
その後B1
現在のコミットに到達する前に、そして- 最新の「ベース」の上にリベースされているブランチは、コミットに基づいています
B3
,見つけようとします
B3
の出力を通過することによって」git rev-list --reflog base
"(すなわちB
,B1
,B2
,B3
)現在のヒントの祖先であるコミットを見つけるまで」Derived (topic)
".内部的には、私たちは持っています
get_merge_bases_many()
それはこれをワンゴーで計算できます。
間にマージベースが必要ですDerived
そして、すべての歴史的なヒントを統合することによって生じる架空の合併コミット」base (origin/master)
".
そのようなコミットが存在する場合、単一の結果を取得する必要があります。base
".
GIT 2.1(2014年第3四半期)は、この機能をより堅牢にします。 1E0DACDをコミットします に ジョンキーピング(johnkeeping
)
次のトポロジがあるシナリオを正しく処理します。
C --- D --- E <- dev
/
B <- master@{1}
/
o --- B' --- C* --- D* <- master
どこ:
B'
の固定バージョンですB
それはパッチが同一ではありませんB
;C*
とD*
パッチが同一ですC
とD
それぞれ間違った順序で適用された場合、それぞれテキストで競合します。E
テキストに依存しますD
.
の正しい結果 git rebase master dev
それです B
フォークポイントとして識別されます dev
と master
, 、 となることによって C
, D
, E
リプレイする必要があるコミットです master
;しかし C
と D
パッチが同一です C*
と D*
そして、最終結果は次のようにするため、ドロップすることができます。
o --- B' --- C* --- D* --- E <- dev
フォークポイントが識別されない場合は、選択します B
含むブランチに B'
競合をもたらし、パッチ同一のコミットが正しく識別されない場合、ピッキング C
含むブランチに D
(または同等に D*
)競合をもたらします。