Wie rette ich / Re-synchronisiert, nachdem jemand ein Fütterungsmaterial oder ein Rücksetzen auf einen veröffentlichten Zweig schiebt?

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

Frage

Wir haben alle gehört, dass man sollte nie rebase Arbeit veröffentlicht, dass es gefährlich ist, usw. Allerdings habe ich keine Rezepte für den Umgang mit der Situation im Falle einer rebase is geschrieben gesehen veröffentlicht .

Nun, tun beachten Sie, dass dies nur dann wirklich möglich, wenn das Repository nur durch eine bekannte (und vorzugsweise kleine) Gruppe von Menschen geklont wird, dass so wer das Fütterungsmaterial drückt oder Reset jeden mitteilt sonst kann, dass sie zu achten brauchen nächstes Mal, wenn sie holen (!).

Eine offensichtliche Lösung, dass ich gesehen habe, wird funktionieren, wenn Sie keine lokalen Commits auf foo haben und es indexiert wird:

git fetch
git checkout foo
git reset --hard origin/foo

Dies wird einfach den lokalen Zustand der foo zugunsten seiner Geschichte gemäß dem Remote-Repository wegzuwerfen.

Aber wie geht man mit der Situation, wenn man erhebliche lokale Änderungen an diesem Zweig begangen hat?

War es hilfreich?

Lösung

Kommen wir zurück synchron nach einer geschoben rebase ist wirklich nicht so in den meisten Fällen kompliziert.

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

Ie. zuerst setzen Sie war ursprünglich ein Lesezeichen für die Position der fernen Zweig, dann verwenden Sie, dass Ihre lokalen Commits von diesem Punkt wiederholen weiter auf umbasiert Fern Zweig.

ist Umbasierung wie Gewalt: Wenn es nicht Ihr Problem lösen, brauchen Sie nur mehr davon. ?

Sie können dies tun, ohne das Lesezeichen natürlich, wenn Sie die Pre-rebase origin/foo begehen ID nachschlagen und Verwendung der.

Dies ist auch, wie man mit der Situation umgehen, wenn Sie ein Lesezeichen machen vergessen vor abgerufen werden. Nichts ist verloren - Sie müssen nur die reflog überprüfen für den Remote-Zweig:

git reflog show origin/foo | awk '
    PRINT_NEXT==1 { print $1; exit }
    /fetch: forced-update/ { PRINT_NEXT=1 }'

Dies druckt die ID verpflichten, dass origin/foo zu spitz, bevor die jüngsten holen, dass seine Geschichte geändert.

Sie können dann einfach

git rebase --onto origin/foo $commit foo

Andere Tipps

würde ich das sagen erholt sich von stromaufwärts rebase Abschnitt des git- rebase Manpage deckt so ziemlich alles.

Es ist wirklich nicht anders aus Ihrer eigenen rebase erholt - Sie bewegen einen Zweig, und rebase alle Zweige, die ihn auf seine neue Position in ihrer Geschichte hatten

.

Beginnend mit git 1.9 / 2.0 Q1 2014 wird Sie nicht Ihre vorherigen Zweig Ursprung markieren müssen, bevor sie auf dem neu geschrieben Upstream-Zweig Rebasing, wie in Aristoteles pagaltzis 's Antwort :
Siehe verpflichten 07d406b und begehen d96855f :

  

Nach der Arbeit auf dem topic Zweig mit git checkout -b topic origin/master erstellt, die Geschichte der Fernverfolgung Zweig origin/master kann zurückgespult und neu aufgebaut wurden, zu einer Geschichte dieser Form führt:

                   o---B1
                  /
  ---o---o---B2--o---o---o---B (origin/master)
          \
           B3
            \
             Derived (topic)
  

wo origin/master bei Commits B3 zu Punkt verwendet, B2, B1 und jetzt zeigt es auf B und Ihr topic Zweig wurde oben drauf zurück beginnt, als origin/master bei B3 war.

     

In diesem Modus wird die reflog von origin/master B3 als Gabelpunkt zu finden, so dass die topic oben auf die aktualisierten indexiert werden können origin/master durch:

$ fork_point=$(git merge-base --fork-point origin/master topic)
$ git rebase --onto origin/master $fork_point topic

Deshalb ist der git merge-base Befehl hat eine neue Option:

--fork-point::
  

Hier finden Sie die Stelle, an der ein Zweig (oder eine Geschichte, dass führt zu <commit>) von einem anderen Zweig gegabelt (oder jeder Referenz) <ref>.
  Das sieht nicht nur für die gemeinsamen Vorfahren der beiden Commits, aber berücksichtigt auch die reflog von <ref> zu sehen, ob die Geschichte, die zu <commit> aus einer früheren Inkarnation der Zweig gegabelt <ref> .


  

Der „git pull --rebase“ Befehl berechnet der Gabelpunkt des Zweig umbasiert wobei die reflog Einträge des „base“ -Zweig (normalerweise ein Fernverfolgung Zweig), um die Arbeit des Zweig beruhte auf, um mit dem Fall fertig zu werden in welche die „Basis“ Zweig hat gewesen zurückgespult und wiederaufgebaut.

Zum Beispiel, wenn die Geschichte sieht aus wie, wo:

  
      
  • die aktuelle Spitze des „base“ Zweig ist auf B, aber früher Abruf festgestellt, dass seine Spitze B3 verwendet werden sollte und dann B2 und dann B1   vor dem aktuellen bekommen begehen, und
  •   
  • die Niederlassung auf die neuesten „Basis“ indexiert werden basiert auf begehen B3,
  •   
     

es versucht B3 zu finden, indem sie durch die Ausgabe von „git rev-list --reflog base“ gehen (das heißt B, B1, B2, B3), bis er eine findet begehen, dass ein Vorfahre der aktuellen Spitze „Derived (topic)“.

     

Intern haben wir get_merge_bases_many(), dass dies mit einem Sprung berechnen kann.
  Wir würden einen Merge-Basis zwischen Derived wollen und einer fiktiven merge commit, dass durch die Zusammenlegung aller historischen Spitzen „base (origin/master)“ führen würde.
  Wenn eine solche exist begehen, sollten wir ein einzelnes Ergebnis bekommen, das ist genau eine der reflog Einträge von „base“ entsprechen.


Git 2.1 (Q3 2014) fügen Sie diese Funktion machen robusteres dazu: siehe begehen 1e0dacd von John Keeping (johnkeeping)

korrekt verarbeiten das Szenario, in dem wirhat die folgende Topologie:

    C --- D --- E  <- dev
   /
  B  <- master@{1}
 /
o --- B' --- C* --- D*  <- master

Dabei gilt:

  • B' ist ein Fest-up-Version von B, die nicht pflaster identisch mit B wird;
  • C* und D* sind pflaster identisch mit C und D jeweils und Konflikt textlich, wenn in der falschen Reihenfolge angewandt wird;
  • E hängt textlich auf D.

Das richtige Ergebnis von git rebase master dev ist, dass B als Gabelpunkt dev und master identifiziert wird, so dass C, D, E sind die Commits, dass Bedarf an master wiederholt werden; aber C und D sind pflaster identisch mit C* und D* und so kann fallen gelassen werden, so dass das Endergebnis ist:

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

Wenn der Gabelpunkt nicht identifiziert, dann Kommissionierung B auf einen Zweig enthält B' führt zu einem Konflikt und wenn die Patch-identisch Commits nicht korrekt dann C auf einen Zweig Kommissionierung identifiziert enthält D (oder äquivalent D*) ergibt ein Konflikt.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top