誰かが公開されているブランチにリベースまたはリセットを押した後、回復/再同期するにはどうすればよいですか?

StackOverflow https://stackoverflow.com/questions/4084868

質問

私たちは皆、公開された作品を決してリベースにしないでください、それが危険であることなどを聞いています。しかし、私はリベースの場合に状況に対処する方法のために投稿されたレシピを見たことがありません 公開。

さて、リポジトリが既知の(そして好ましくは小さい)グループによってのみクローン化されている場合にのみ、これは本当に実現可能であることに注意してください。フェッチ(!)。

私が見た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 答え:
見る コミット07d406bD96855Fをコミットします :

に取り組んだ後 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* パッチが同一です CD それぞれ間違った順序で適用された場合、それぞれテキストで競合します。
  • E テキストに依存します D.

の正しい結果 git rebase master dev それです B フォークポイントとして識別されます devmaster, 、 となることによって C, D, E リプレイする必要があるコミットです master;しかし CD パッチが同一です C*D* そして、最終結果は次のようにするため、ドロップすることができます。

o --- B' --- C* --- D* --- E  <- dev

フォークポイントが識別されない場合は、選択します B 含むブランチに B' 競合をもたらし、パッチ同一のコミットが正しく識別されない場合、ピッキング C 含むブランチに D (または同等に D*)競合をもたらします。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top