Git-Zweig divergierte nach Rebase

112

Ich habe eine Filiale vor Ort neu gegründet, die bereits gepusht wurde.

Git weist darauf hin, dass mein Zweig und meine Fernbedienung auseinander gegangen sind und dass:

"und haben jeweils 109 und 73 verschiedene Commits"

Wird das Drücken meines Zweigs dieses Problem beheben - dh ist dies nach einer erneuten Basis zu erwarten?

Marty Wallace
quelle
Ich habe das gleiche Problem. Können wir sagen, dass "der richtige Weg" darin besteht, den lokalen Zweig neu zu gründen und erst dann zu pushen?
Mher Didaryan

Antworten:

154

Wenn Sie einen Zweig neu gründen, müssen Sie die Commits für alle Commits neu schreiben, die über den Commits in dem Zweig liegen, auf den Sie neu gründen. Dies liegt daran, dass eine der Eigenschaften eines Commits dessen übergeordnetes Element (oder übergeordnete Elemente) ist. Wenn Sie die Basis neu festlegen, ändern Sie das übergeordnete Element des ältesten lokalen Commits in Ihrem Zweig - und damit die Commit-Hashes aller Ihrer lokalen Commits, da diese Änderung transitiv durch die Commits sprudelt.

Da Sie den Zweig bereits verschoben haben, sollten Sie ihn im Quellzweig zusammenführen, anstatt ihn erneut zu verwenden. Es ist möglich, Ihren neuen Zweig (mithilfe des -fFlags) zu "erzwingen" , aber ein normaler Druck funktioniert nicht, da die Integrität des Zweigverlaufs gestört wird. Wenn Sie in diesem Zweig mit anderen zusammenarbeiten, ist Force Pushing eine schlechte Idee, da andere Mitarbeiter dadurch sehr verwirrt werden, wenn ihre Historie plötzlich nicht mehr übereinstimmt.

TL; DR - Wenn Sie nicht zusammenarbeiten, verschieben Sie den Zweig mit push -f. Wenn dies der Fall ist, setzen Sie den Zweig auf den vorherigen Status zurück und führen Sie stattdessen den Quellzweig zusammen.

Jason LeBrun
quelle
1
"Da Sie den Zweig bereits verschoben haben, sollten Sie ihn im Quellzweig zusammenführen" - warum ist das so?
Hammett
1
@HamiltonVerissimo Jasons erster Satz: "Wenn Sie einen Zweig neu gründen, müssen Sie die Commits für jeden Commit neu schreiben, der über den Commits in dem Zweig liegt, auf den Sie neu gründen." Obwohl die in den "obigen" Commits erfassten Änderungen denselben logischen Inhalt haben, werden sie auf eine andere Basis angewendet und sind daher unterschiedliche Commits mit unterschiedlichen Hashes. Wenn andere Entwickler aus dem vorinstallierten Zweig heraus arbeiten, würde ein Git-Push -f ihren Workflow extrem stören. Da dieser Zweig an eine öffentliche Quelle weitergegeben wurde, hätte er sich zusammenschließen sollen.
Awolf
4
Sie können auch push --force-with-lease verwenden, wenn Sie nicht sicher sind, ob bereits jemand etwas gepusht hat.
Konsole
1
@ jason-lebrun Ist es nicht der Nachteil beim Zusammenführen der vorgelagerten Änderungen, dass Sie Ihre eigene Arbeit ohne Vorwarnung überschreiben können? Werden Zusammenführungskonflikte auf dieselbe Weise wie beim erneuten Basieren erkannt? Wenn ich beispielsweise einen Abschnitt aus einer Datei in meinem Zweig entferne, weil er nicht mehr benötigt wird, aber jemand anderes eine geringfügige Änderung am selben Abschnitt im Upstream vorgenommen hat, z. B. das Entfernen von Leerzeichen oder eine globale Such- / Ersetzungsaktion, würde dies nicht der Fall sein Zusammenführen über meinem Zweig Ersetzen Sie meine Löschung durch ihre trivial geänderte Version?
Chris Bloom
1
Ist es keine schlechte Idee, den anderen Zweig mit Ihrem zusammenzuführen? ZB Master in einen Feature-Zweig einbinden - wird dadurch kein neues Commit dafür erstellt? Wird dies nicht zu einem zusätzlichen Commit führen, sobald dieser Feature-Zweig vorhanden ist, wenn er später zum Master zusammengeführt wird?
Ross
55

Alle Ihre Commits haben ihre IDs geändert, sodass die Umleitung nicht wirklich divergiert.

Um Ihr Problem zu lösen , müssen Sie Ihren Remote-Zweig überschreiben:

git push -f origin experiment

http://git-scm.com/book/ch3-6.html

Erläuterung:

Sehen Sie, wie in diesem Bild C3 nach der Rebase nicht als C3, sondern als C3 'gesetzt wird. Dies liegt daran, dass es nicht genau C3 ist, aber alle Codeänderungen enthält.

Rebase

Auf diesem anderen Bild sehen Sie, was eine Rebase ist, wenn eine Fernbedienung beteiligt ist, und warum es eine Umleitung gibt.

divergieren und git schieben

In jedem Fall wird Ihnen nach dem erzwungenen Push mitgeteilt, dass ein (Force Update) durchgeführt wurde. An diesem Punkt sollte es Ihnen gut gehen.

Kasse den Link oben und suche nach "git push --force". Sie sehen eine detailliertere Erklärung.

mimoralea
quelle
3
Jep. Ich denke, das löst das Problem. Force Push funktioniert jedoch möglicherweise nicht, wenn Sie in einem Team arbeiten, wenn Ihr Push möglicherweise die kürzlich von anderen geschobenen Arbeiten überschreibt. Habe ich recht?
Hari Krishna Ganji
Es hat möglicherweise nicht die gewünschten Effekte. Stellen Sie sicher, dass Sie Ihre Änderungen "Schnellvorlauf" zusammenführen, bevor Sie die Rebase durchführen.
Mimoralea
1

Ich hatte Erfolg mit der Rebase-Divergenz für einen Push, indem ich Folgendes tat:

git checkout mybranch
git pull
git push origin mybranch

Der Zug löste die Divergenz.

VOR dem Ziehen

Your branch and 'origin/mybranch' have diverged,
and have 2 and 1 different commit(s) each, respectively.

PULL-Ausgabe

Zusammenführung durch rekursive. mypath / myfile.py | 12 +++++++++++ - 1 Dateien geändert, 11 Einfügungen (+), 1 Löschungen (-)

Nach dem Ziehen

Ihre Filiale liegt 3 Commits vor 'origin / mybranch'.

NACH DEM DRÜCKEN

mybranch ist 3 vor dem Zweig, dem noch eine offene Pull-Request-Merge-Nachricht zum Commit-Verlauf hinzugefügt wurde. Zweig mybranch von remote in mybranch zusammenführen

Ich gehe davon aus, dass dies wahrscheinlich das ist, was der Kraftschub bewirkt, und ich habe es nicht überprüft.

Vermeiden Sie, wie die anderen gesagt haben, eine Rebase, wenn Sie bereits eine Open-Pull-Anfrage haben. Ich gebe dieses Beispiel als etwas, das für mich funktioniert hat.

Nullocog
quelle
1

Dies kann ohne erzwungenen Druck behoben werden, indem der Zielzweig in Ihren aktuellen lokalen Zweig umbasiert, zu Ihrem Zielzweig gewechselt und dann Ihr lokaler Zweig in das Ziel umbasiert wird. Dies geht nicht auseinander, da die möglicherweise fehlenden Commits hinzugefügt werden und nicht mehr erstellt werden müssen. Beispiel zur einfacheren Erklärung:

  1. Hauptzweig ist zu entwickeln
  2. Sie checken eine neue Verzweigungsfunktion / mache_Stuff aus
  3. Ein Teammitglied drängt auf ein neues Engagement, um sich zu entwickeln

Wenn Sie Ihren Entwicklungszweig NICHT aktualisiert haben, funktioniert eine "Git-Checkout-Entwicklung" && "Git-Rebase-Funktion / Doing_stuff" ordnungsgemäß, da seit dem Checkout keine Commits hinzugefügt wurden. Wenn Sie jedoch die Entwicklung ausgecheckt und das neue Commit heruntergezogen haben, werden Sie diese Abweichung feststellen, wenn Sie versuchen, die Basis neu zu erstellen, da ein neues Commit angezeigt wird. Eine einfache Lösung ohne erzwungenes Drücken (normalerweise keine gute Idee in einer Teamumgebung) ist:

  1. Git Checkout Feature / Doing_Stuff
  2. Git Rebase entwickeln
  3. Git Checkout entwickeln
  4. Git Rebase Feature / Doing_Stuff

Die Rebase aus Schritt 2 bringt das fehlende Commit in das Feature / Doing_stuff, sodass es in Schritt 4 auf dem neuesten Stand ist und kein neues Commit für die Änderung erstellen muss.

Dies ist eine Lösung, von der ich weiß, dass sie funktioniert, weil ich gerade darauf gestoßen bin und die oben genannten Schritte ausgeführt habe, um die Entwicklung erfolgreich voranzutreiben, ohne sie zu erzwingen. Ich arbeite in einem Team von über 50 Entwicklern, daher ist es verboten, etwas anderes als meine eigenen Testzweige zu erzwingen, sodass ich eine Lösung finden musste.

Chris
quelle