Wie kann ich eine Git-Rebase einfach rückgängig machen?
Meine aktuellen Ideen sind nur manuelle Ansätze:
git checkout
auf dem Commit-Elternteil für beide Zweige- Erstellen Sie von dort aus einen temporären Zweig
git cherry-pick
alle Commits von Hand- Ersetzen Sie den Zweig, in dem ich neu basiert habe, durch den manuell erstellten Zweig
In meiner aktuellen Situation würde dies funktionieren, da ich Commits aus beiden Zweigen leicht erkennen kann (einer war mein Zeug, der andere war das Zeug meines Kollegen).
Mein Ansatz erscheint mir jedoch suboptimal und fehleranfällig (sagen wir, ich habe gerade mit 2 meiner eigenen Zweige neu basiert).
Klarstellung : Ich spreche von einer Rebase, bei der eine Reihe von Commits wiederholt wurden. Nicht nur einer.
git
rebase
git-rebase
undo
Webmat
quelle
quelle
Antworten:
Der einfachste Weg wäre, das Head-Commit des Zweigs zu finden, wie es unmittelbar vor dem Start der Rebase im Reflog war ...
und um den aktuellen Zweig darauf zurückzusetzen (mit den üblichen Einschränkungen, dass Sie vor dem Zurücksetzen mit der
--hard
Option absolut sicher sind ).Angenommen, das alte Commit befand sich
HEAD@{5}
im Referenzprotokoll:In Windows müssen Sie möglicherweise die Referenz angeben:
Sie können den Verlauf des alten Kopfes des Kandidaten überprüfen, indem Sie einfach ein
git log HEAD@{5}
( Windows :) ausführengit log "HEAD@{5}"
.Wenn Sie nicht pro Zweig-Reflogs deaktiviert haben, sollten Sie dies einfach tun können,
git reflog branchname@{1}
da eine Rebase den Zweigkopf abtrennt, bevor Sie ihn wieder an den endgültigen Kopf anschließen. Ich würde dies jedoch noch einmal überprüfen, da ich dies kürzlich nicht überprüft habe.Standardmäßig sind alle Reflogs für nicht nackte Repositorys aktiviert:
quelle
git log -g
(Tipp von Scott Chacons progit.org/book ) eine besser formatierte Ausgabe erhalten können .git rebase --abort
(-i
macht keinen Sinn mit--abort
) dient dazu, eine nicht abgeschlossene Rebase aufzugeben - entweder weil es Konflikte gab oder weil sie interaktiv war oder beides; Es geht nicht darum, eine erfolgreiche Rebase rückgängig zu machen, worum es bei der Frage geht. Sie würden entweder verwendenrebase --abort
oderreset --hard
abhängig davon, in welcher Situation Sie sich befanden. Sie sollten nicht beides tun müssen.git tag BACKUP
. Sie können darauf zurückkommen, wenn etwas schief geht:git reset --hard BACKUP
commit:
im Gegensatz zu vorangestelltrebase:
. Klingt offensichtlich, hat mich aber ein bisschen verwirrt.git reset --hard ORIG_HEAD
den Trick nicht auch sofort nach dem versehentlichen Rebase machen?Tatsächlich speichert Rebase Ihren Ausgangspunkt,
ORIG_HEAD
sodass dies normalerweise so einfach ist wie:Doch das
reset
,rebase
undmerge
alle speichern Ihre ursprünglicheHEAD
Zeiger in demORIG_HEAD
so ist , wenn Sie noch eine dieser Befehle durchgeführt , da die rebase Sie rückgängig machen sind versuchen , dann werden Sie die reflog verwenden.quelle
ORIG_HEAD
nicht mehr sinnvoll ist, können Sie auch diebranchName@{n}
Syntax verwenden, wobein
die n-te vorherige Position des Verzweigungszeigers ist. Wenn Sie beispielsweise diefeatureA
Verzweigung auf Ihremaster
Verzweigung neu stützen, das Ergebnis der Neubasis jedoch nicht gefällt, können Siegit reset --hard featureA@{1}
die Verzweigung einfach auf den genauen Stand zurücksetzen, an dem sie sich vor der Neubasis befand. Weitere Informationen zur branch @ {n} -Syntax finden Sie in den offiziellen Git-Dokumenten für Überarbeitungen .git rebase --abort
obwohl.git 2.17.0
.git reset --hard ORIG_HEAD
Kann wiederholt verwenden, um immer wieder zurückzurollen. Sagen wir, wenn A --- Rebase zu --- B --- Rebase zu --- C, jetzt bin ich bei C, kann ich zweimal zu A zurückkehrengit reset --hard ORIG_HEAD
git rebase --abort
?Charles 'Antwort funktioniert, aber vielleicht möchten Sie dies tun:
nach dem aufräumen
reset
.Andernfalls erhalten Sie möglicherweise die Meldung "
Interactive rebase already started
".quelle
Das Zurücksetzen des Zweigs auf das baumelnde Festschreibungsobjekt seiner alten Spitze ist natürlich die beste Lösung, da der vorherige Zustand ohne großen Aufwand wiederhergestellt wird. Wenn Sie diese Commits jedoch verloren haben (z. B. weil Sie in der Zwischenzeit Ihr Repository mit Müll gesammelt haben oder dies ein neuer Klon ist), können Sie den Zweig jederzeit erneut neu starten. Der Schlüssel dazu ist der
--onto
Schalter.Angenommen , Sie haben ein Thema Zweig hatte phantasievoll genannt
topic
, dass Sie abgezweigt ,master
wenn die Spitzemaster
der war zu0deadbeef
begehen. Irgendwann auf demtopic
Ast hast du es getangit rebase master
. Jetzt möchten Sie dies rückgängig machen. Hier ist wie:Dadurch werden alle
topic
nichtmaster
aktivierten Commits übernommen und zusätzlich wiedergegeben0deadbeef
.Mit
--onto
können Sie Ihre Geschichte in nahezu jede Form umwandeln .Habe Spaß. :-)
quelle
--onto
und-i
Sie Ihre Geschichte in so ziemlich jede Form neu ordnen können. Verwenden Sie gitk (oder gitx auf dem Mac), um die Formen zu sehen, die Sie erstellen :-).Ich habe tatsächlich ein Backup-Tag in den Zweig eingefügt, bevor ich eine nicht triviale Operation ausführe (die meisten Rebases sind trivial, aber ich würde das tun, wenn es irgendwo komplex aussieht).
Dann ist das Wiederherstellen so einfach wie
git reset --hard BACKUP
.quelle
branchName@{n}
Syntax verwenden. Hiern
ist die n-te vorherige Position des Verzweigungszeigers. Wenn Sie beispielsweise diefeatureA
Verzweigung auf Ihremaster
Verzweigung neu stützen, das Ergebnis der Neubasis jedoch nicht gefällt, können Siegit reset --hard featureA@{1}
die Verzweigung einfach auf den genauen Stand zurücksetzen, an dem sie sich vor der Neubasis befand. Weitere Informationen zurbranch@{n}
Syntax finden Sie in den offiziellen Git-Dokumenten für Überarbeitungen .HEAD
des Zweigs vorübergehend in gespeichertORIG_HEAD
. Aber die Technik der Verwendung eines Backup-Zweigetiketts funktioniert auch, es sind nur mehr Schritte.Für den Fall , Sie hatten Ihre Niederlassung zu Remote - Repository geschoben ( in der Regel seinen Ursprung) und dann haben Sie eine succesfull rebase (ohne Zusammenführung) durchgeführt (
git rebase --abort
gibt „Nein im Gange rebase“) können Sie einfach zurückgesetzt Zweig mit dem Befehl:Beispiel:
quelle
Verwenden
reflog
hat bei mir nicht funktioniert.Was für mich funktionierte, war ähnlich wie hier beschrieben . Öffnen Sie die Datei in .git / logs / refs, die nach dem Zweig benannt ist, der neu basiert wurde, und suchen Sie die Zeile, die "rebase finsihed" enthält.
Überprüfen Sie das zweite in der Zeile aufgeführte Commit.
Nachdem ich bestätigt hatte, dass dies meine verlorenen Veränderungen enthielt, verzweigte ich mich und seufzte erleichtert auf.
quelle
Denken Sie bei mehreren Commits daran, dass jedes Commit auf den gesamten Verlauf verweist, der zu diesem Commit geführt hat. Lesen Sie in Charles 'Antwort "das alte Commit" als "das neueste der alten Commits". Wenn Sie auf dieses Commit zurücksetzen, wird der gesamte Verlauf dieses Commits erneut angezeigt. Dies sollte tun, was Sie wollen.
quelle
Nach der Lösung von @Allan und @Zearin wünschte ich mir, ich könnte einfach einen Kommentar abgeben, aber ich habe nicht genug Ruf, deshalb habe ich den folgenden Befehl verwendet:
Anstatt zu tun
git rebase -i --abort
(beachte das -i ), musste ich einfach machengit rebase --abort
( ohne das -i ).Beide unter Verwendung von
-i
und--abort
zur gleichen Zeit verursacht Git mir eine Liste der Verwendungs / Optionen anzuzeigen.Mein bisheriger und aktueller Zweigstellenstatus bei dieser Lösung lautet also:
quelle
Wenn Sie erfolgreich gegen Remote Branch verzweigt haben und dies nicht
git rebase --abort
können, können Sie dennoch einige Tricks ausführen , um Ihre Arbeit zu retten, und keine erzwungenen Pushs ausführen . Angenommen, Ihr aktueller Zweig, der versehentlich neu basiert wurde, wird aufgerufenyour-branch
und verfolgtorigin/your-branch
git branch -m your-branch-rebased
# aktuellen Zweig umbenennengit checkout origin/your-branch
# Auschecken in den neuesten Status, dessen Ursprung bekannt istgit checkout -b your-branch
git log your-branch-rebased
, vergleichengit log your-branch
und definieren Sie Commits, die in fehlenyour-branch
git cherry-pick COMMIT_HASH
für jedes Commit inyour-branch-rebased
remote/your-branch
und Sie nur pushen solltenyour-branch
quelle
Angenommen, ich stütze den Master auf meinen Feature-Zweig zurück und erhalte 30 neue Commits, die etwas beschädigen. Ich habe festgestellt, dass es oft am einfachsten ist, nur die schlechten Commits zu entfernen.
Interaktive Rebase für die letzten 31 Commits (es tut nicht weh, wenn Sie viel zu viele auswählen).
Nehmen Sie einfach die Commits, die Sie entfernen möchten, und markieren Sie sie mit "d" anstelle von "pick". Jetzt werden die Commits gelöscht und die Rebase effektiv rückgängig gemacht (wenn Sie nur die Commits entfernen, die Sie gerade beim Rebasis erhalten haben).
quelle
Für Neulinge / alle, die Angst vor einem Hard-Reset haben, können Sie das Commit aus dem Reflog auschecken und dann als neuen Zweig speichern.
Suchen Sie das Commit, bevor Sie mit der Neugründung beginnen. Möglicherweise müssen Sie weiter nach unten scrollen, um es zu finden (drücken Sie die Eingabetaste oder PageDown). Notieren Sie sich die HEAD-Nummer und ersetzen Sie 57:
Überprüfen Sie den Zweig / die Commits. Wenn es gut aussieht, erstellen Sie einen neuen Zweig mit diesem HEAD:
quelle
Wenn Sie sich in einer Filiale befinden, können Sie Folgendes verwenden:
Es gibt nicht nur ein Referenzprotokoll für HEAD (erhalten von
git reflog
), sondern auch Reflogs für jeden Zweig (erhalten vongit reflog <branch>
). Also, wenn Sie sind aufmaster
danngit reflog master
werden alle Änderungen Liste auf diesen Zweig. Sie können zu , dass Änderungen beziehenmaster@{1}
,master@{2}
usw.git rebase
wird normalerweise HEAD mehrmals ändern, aber der aktuelle Zweig wird nur einmal aktualisiert.@{1}
ist einfach eine Verknüpfung für den aktuellen Zweig , also ist es gleich,master@{1}
wenn Sie eingeschaltet sindmaster
.git reset --hard ORIG_HEAD
funktioniert nicht, wenn Siegit reset
während einer interaktiven verwendetrebase
.quelle
Was ich normalerweise mache ist
git reset #commit_hash
bis zum letzten Commit, wo meiner Meinung nach Rebase keine Wirkung hatte.
dann
git pull
Jetzt sollte Ihr Zweig genau wie Master übereinstimmen und neu basierte Commits sollten nicht darin enthalten sein.
Jetzt kann man nur noch die Commits in diesem Zweig auswählen.
quelle
Ich habe alle Vorschläge mit Reset und Reflog ohne Erfolg ausprobiert. Durch das Wiederherstellen des lokalen Verlaufs von IntelliJ wurde das Problem verlorener Dateien behoben
quelle
git reset --hard origin / {branchName}
ist die richtige Lösung, um alle durch Rebase vorgenommenen lokalen Änderungen zurückzusetzen.
quelle
origin/branch
verlieren Sie möglicherweise Änderungen zwischen HEAD und diesem Punkt. Das wollen Sie im Allgemeinen nicht.Wenn Sie innerhalb einer Git-Rebase etwas durcheinander bringen, z. B.
git rebase --abort
wenn Sie nicht festgeschriebene Dateien haben, gehen diese verloren undgit reflog
helfen nicht weiter. Das ist mir passiert und Sie müssen hier über den Tellerrand hinaus denken. Wenn Sie Glück haben wie ich und IntelliJ Webstorm verwenden, könnenright-click->local history
und können Sie zu einem früheren Status Ihrer Datei / Ordner zurückkehren, unabhängig davon, welche Fehler Sie mit der Versionssoftware gemacht haben. Es ist immer gut, wenn eine andere Ausfallsicherheit ausgeführt wird.quelle
git rebase --abort
bricht eine aktive Rebase ab, macht eine Rebase nicht rückgängig . Es ist auch eine schlechte Idee, zwei VCS gleichzeitig zu verwenden. Es ist eine nette Funktion in der Jetbrains-Software, aber Sie sollten nicht beide verwenden. Es ist besser, nur Git zu lernen, insbesondere wenn Sie Fragen zu Stack Overflow beantworten, die sich mit Git befassen.