Wiederholen einer rückgängig gemachten Zusammenführung in Git


231

Ich bin hier auf ein kleines Problem gestoßen: Ich hatte einen problemspezifischen Zweig 28sin Git, den ich im allgemeinen developZweig zusammengeführt habe. Es stellte sich heraus, dass ich es zu schnell gemacht hatte, also habe ich git-revert verwendet, um die Zusammenführung rückgängig zu machen. Nun aber ist die Zeit gekommen zu verschmelzen 28sin develop, aber git-merge - Befehl sieht die ursprüngliche merge, und kündigt glücklich , dass alles gut ist und Filialen sind bereits verschmolzen. Was mache ich jetzt? Erstellen Sie ein 'Revert "Revert" 28s -> Develop ""' Commit? Scheint kein guter Weg zu sein, aber ich kann mir im Moment keinen anderen vorstellen.

Wie die Baumstruktur aussieht:

Git-Protokollausgabe


4
Es ist GitX ( gitx.frim.nl ).
Toms Mikoss

Antworten:


169

Sie müssen "das Zurücksetzen rückgängig machen". Abhängig davon, wie das Original wiederhergestellt wurde, ist es möglicherweise nicht so einfach, wie es sich anhört. Schauen Sie sich das offizielle Dokument zu diesem Thema an .

---o---o---o---M---x---x---W---x---Y
              /
      ---A---B-------------------C---D

erlauben:

---o---o---o---M---x---x-------x-------*
              /                       /
      ---A---B-------------------C---D

Aber funktioniert alles? Sicher tut es das. Sie können eine Zusammenführung rückgängig machen, und aus rein technischer Sicht hat git dies ganz natürlich getan und hatte keine wirklichen Probleme.
Es wurde nur als Wechsel von "Status vor dem Zusammenführen" zu "Status nach dem Zusammenführen" betrachtet, und das war es.
Nichts Kompliziertes, nichts Seltsames, nichts wirklich Gefährliches. Git wird es tun, ohne darüber nachzudenken.

Aus technischer Sicht ist es also nichts Falsches, eine Zusammenführung zurückzusetzen, aber aus Workflow-Sicht sollten Sie dies generell vermeiden .

Wenn möglich, zum Beispiel, wenn Sie ein Problem finden , die in die Haupt-Sammlung aufgenommen wurden, anstatt revert der Zusammenführung, versuche wirklich schwer zu :

  • halbieren Sie das Problem in den Zweig, den Sie zusammengeführt haben, und beheben Sie es einfach.
  • oder versuchen Sie, das einzelne Commit, das es verursacht hat, zurückzusetzen.

Ja, es ist komplizierter, und nein, es ist nicht immer zur Arbeit gehen (manchmal ist die Antwort: „oops, ich sollte wirklich nicht fusionierte sie haben, denn es ist noch nicht fertig war, und ich brauche wirklich rückgängig machen alle von der verschmelzen"). Dann sollten Sie die Zusammenführung wirklich zurücksetzen, aber wenn Sie die Zusammenführung erneut durchführen möchten, müssen Sie dies jetzt tun, indem Sie die Rückstellung zurücksetzen.


10
Guter Link (+1). Ich habe mir erlaubt, einen Teil des Dokuments in Ihre Antwort zu kopieren, damit die Leser die relevanten Optionen in diesem Fall sofort sehen können. Wenn Sie nicht einverstanden sind, können Sie jederzeit zurückkehren.
VonC

5
Wir sind gerade auf einen Fall gestoßen, in dem wir dies tun mussten, und haben festgestellt, dass der Spaß hier nicht ganz aufhört. Es war ein lang laufender Zweig, der zusammengeführt wurde, daher mussten wir ihn weiter aktualisieren. Mein Ansatz hier: tech.patientslikeme.com/2010/09/29/…
jdwyah

Ich folgte @ jdwyahs Blog-Post und es war herrlich (im Ernst, es war großartig, dass es einfach funktioniert hat).
Hellatan

2
@jdwyah das scheint ein defekter Link zu sein, aber es klingt nach einer interessanten Lektüre. Hier ist ein archive.org Spiegel, aber es fehlen die Bilder: web.archive.org/web/20111229193713/http://…
Alex KeySmith

15
Blog-Beitrag wurde wiederbelebt, danke: blog.jdwyah.com/2015/07/dealing-with-git-merge-revisions.html
jdwyah

53

Nehmen wir an, Sie haben eine solche Geschichte

---o---o---o---M---W---x-------x-------*
              /                      
      ---A---B

Wenn A, B fehlgeschlagen ist und W - von M zurückgesetzt wird

Bevor ich anfange, festgestellte Probleme zu beheben, wähle ich W Commit für meinen Zweig aus

git cherry-pick -x W

Dann setze ich das W-Commit für meinen Zweig zurück

git revert W 

Nachdem ich weiter reparieren kann.

Die endgültige Geschichte könnte folgendermaßen aussehen:

---o---o---o---M---W---x-------x-------*
              /                       /     
      ---A---B---W---W`----------C---D

Wenn ich eine PR sende, wird deutlich, dass PR rückgängig gemacht wird, und es werden einige neue Commits hinzugefügt.


3
Dies scheint hilfreich zu sein, ist aber so spärlich in den Details (was sind C, D im letzten Diagramm), dass es eher frustrierend als nützlich ist
Isochronous

4
@Isochronous C und D scheinen Commits zu sein, die die von A und B eingeführten Probleme beheben.
Thomas

@ Thomas genau
Maksim Kotlyar

Es ist gut, dass Sie in diesem Fall die Verwendung einer PR hervorgehoben haben, da diese eine endgültige Überprüfung der geistigen Gesundheit ermöglichen kann, bevor Sie wieder zum Master zurückkehren.
Willem van Ketwich

Verwenden Sie, warum starten Sie Ihren Zweig vom ursprünglichen W neu? Dh, lassen Sie Ihr Thema von W fortfahren, mit W` gefolgt von C und D? Das beseitigt einige Überschneidungen
Erik Carstensen

12

So setzen Sie die Wiederherstellung zurück, ohne Ihren Workflow zu stark zu beeinträchtigen:

  • Erstellen Sie eine lokale Papierkorbkopie von Develop
  • Setzen Sie das Revert-Commit für die lokale Kopie von Develop zurück
  • Führen Sie diese Kopie in Ihrem Feature-Zweig zusammen und übertragen Sie Ihren Feature-Zweig auf Ihren Git-Server.

Ihr Feature-Zweig sollte nun wie gewohnt zusammengeführt werden können, wenn Sie dazu bereit sind. Der einzige Nachteil hierbei ist, dass Sie einige zusätzliche Merge / Revert-Commits in Ihrem Verlauf haben.


Um weitere Verwechslungen zu vermeiden, habe ich auch eine "Papierkorb" -Kopie meines Feature-Zweigs erstellt und die rückgängig gemachte Entwicklung darin zusammengeführt.
jhhwilliams

Danke dir! Dies ist die einzige Antwort, die tatsächlich erklärt, wie es geht, anstatt zu sagen, dass Sie dies nicht tun sollten. Wirklich hilfreich.
Emmy

Danke, das hat mir wirklich geholfen. :)
Daniel Stracaboško

11

So setzen Sie eine Wiederherstellung in GIT zurück:

git revert <commit-hash-of-previous-revert>

1
Verwenden Sie dies in meinem Arbeitszweig, um das Zurücksetzen rückgängig zu machen, und entwickeln Sie dann neue PR. Jetzt sieht git alle Änderungen in der vorherigen PR, die zurückgesetzt wurden. Vielen Dank.
Danstan

3

Anstatt zu verwenden, hätten git-revertSie diesen Befehl in der develVerzweigung verwenden können, um das falsche Zusammenführungs-Commit wegzuwerfen (rückgängig zu machen) (anstatt es nur zurückzusetzen).

git checkout devel
git reset --hard COMMIT_BEFORE_WRONG_MERGE

Dadurch wird auch der Inhalt des Arbeitsverzeichnisses entsprechend angepasst. Sei vorsichtig :

  • Speichern Sie Ihre Änderungen im Entwicklungszweig (seit der falschen Zusammenführung), da auch diese von der gelöscht werden git-reset. Alle Commits nach dem von Ihnen als git resetArgument angegebenen Commit werden gelöscht!
  • Tun Sie dies auch nicht, wenn Ihre Änderungen bereits aus anderen Repositorys abgerufen wurden, da beim Zurücksetzen der Verlauf neu geschrieben wird.

Ich empfehle, die git-resetManpage sorgfältig zu lesen, bevor Sie dies versuchen.

Jetzt können Sie nach dem Zurücksetzen Ihre Änderungen erneut anwenden develund dann tun

git checkout devel
git merge 28s

Dies wird ein echter Druck aus seinem 28sin develwie die anfänglichen (die jetzt von git Geschichte gelöscht wird).


8
Für alle, die mit git nicht besonders vertraut sind und diese Anweisungen befolgen möchten: Vorsicht beim Kombinieren von reset --hardund push origin. Beachten Sie auch, dass ein Force Push to Origin offene PRs auf GitHub wirklich durcheinander bringen kann.
Funroll

Sehr hilfreich, um einige Zusammenführungsprobleme auf einem privaten Git-Server zu beheben. Vielen Dank!
mix3d

1
+1 für diese Technik. Potenziell destruktiv, kann Ihnen aber bei vernünftiger Anwendung viel Kopfschmerzen (und eine verstümmelte Vorgeschichte) ersparen.
Siliconrockstar

1

Ich habe diesen Beitrag gerade gefunden, als ich vor dem gleichen Problem stand. Ich finde es oben ziemlich schwierig, Reset-Hards usw. zurückzusetzen. Am Ende lösche ich etwas, das ich nicht möchte, und werde es nicht zurückbekommen können.

Stattdessen habe ich das Commit überprüft, zu dem der Zweig zurückkehren soll, z git checkout 123466t7632723. Dann in einen Zweig umgewandelt git checkout my-new-branch. Ich habe dann den Zweig gelöscht, den ich nicht mehr wollte. Dies funktioniert natürlich nur, wenn Sie den Zweig, den Sie durcheinander gebracht haben, wegwerfen können.


1
Das git reflogschützt Sie für ein paar Monate vor einem Hard-Reset, falls Sie später feststellen, dass Sie die verlorenen Commits benötigen. Das Reflog ist auf Ihr lokales Repo beschränkt.
Todd

1

Ich würde Ihnen empfehlen, die folgenden Schritte auszuführen, um eine Wiederherstellung rückgängig zu machen, z. B. SHA1.

git checkout develop #go to develop branch
git pull             #get the latest from remote/develop branch
git branch users/yourname/revertOfSHA1 #having HEAD referring to develop
git checkout users/yourname/revertOfSHA1 #checkout the newly created branch
git log --oneline --graph --decorate #find the SHA of the revert in the history, say SHA1
git revert SHA1
git push --set-upstream origin users/yourname/revertOfSHA1 #push the changes to remote

Erstellen Sie nun PR für die Branche users/yourname/revertOfSHA1


1
  1. Erstellen Sie vor dem ursprünglichen Zusammenführen einen neuen Zweig beim Festschreiben. Nennen Sie ihn "Entwicklungsbasis".
  2. Führen Sie eine interaktive Rebase von "Entwickeln" über "Entwickeln-Basis" durch (obwohl es bereits oben ist). Während der interaktiven Rebase haben Sie die Möglichkeit, sowohl das Zusammenführungs-Commit als auch das Commit zu entfernen, das die Zusammenführung rückgängig gemacht hat, dh beide Ereignisse aus dem Git-Verlauf zu entfernen

Zu diesem Zeitpunkt haben Sie einen sauberen "Entwicklungs" -Zweig, in den Sie Ihr Feature-Brach wie gewohnt zusammenführen können.


Dieser Ansatz führt zu Problemen, wenn der Entwicklungszweig mit anderen geteilt wird.
PSR
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.