Zusammenfassung
Die Fehlermeldung
Kann nicht "squashen" ohne einen vorherigen Commit
deutet darauf hin, dass Sie wahrscheinlich versucht haben, "nach unten zu squashen". Git squash immer einen neueren Commit in einen älteren Commit oder "nach oben" wie in der interaktiven Neuabstimmung-Todo-Liste angezeigt, das heißt in einen Commit auf einer vorherigen Zeile. Die Änderung des Befehls in der allerersten Zeile Ihrer Todo-Liste auf squash
wird immer diesen Fehler erzeugen, da es nichts gibt, in das der erste Commit squashen kann.
Die Lösung
Kommen Sie zuerst zurück dahin, wo Sie begonnen haben mit
$ git rebase --abort
Sagen wir, Ihre Historie ist
$ git log --pretty=oneline
a931ac7c808e2471b22b5bd20f0cad046b1c5d0d c
b76d157d507e819d7511132bdb5a80dd421d854f b
df239176e1a2ffac927d8b496ea00d5488481db5 a
Das heißt, a war der erste Commit, dann b und schließlich c. Nach Committing c entscheiden wir uns, b und c zusammenzufassen:
(Hinweis: Wenn Sie git log
ausführen, wird die Ausgabe standardmäßig auf den meisten Plattformen in einen Pager, less
, geleitet. Um den Pager zu verlassen und zum Befehls-Prompt zurückzukehren, drücken Sie die q
-Taste.)
Das Ausführen von git rebase --interactive HEAD~2
gibt Ihnen einen Editor mit
pick b76d157 b
pick a931ac7 c
# Rebase df23917..a931ac7 auf df23917
#
# Befehle:
# p, pick = Commit verwenden
# r, reword = Commit verwenden, aber die Commit-Nachricht bearbeiten
# e, edit = Commit verwenden, aber anhalten zum Ändern
# s, squash = Commit verwenden, aber mit vorherigem Commit verschmelzen
# f, fixup = wie "squash", aber die Commit-Lognachricht dieses Commits verwerfen
#
# Wenn Sie hier eine Zeile entfernen, WIRD DER COMMIT VERLOREN GEHEN.
# Wenn Sie jedoch alles entfernen, wird die Neuabstimmung abgebrochen.
#
(Beachten Sie, dass diese ToDo-Liste in umgekehrter Reihenfolge im Vergleich zur Ausgabe von git log
ist.)
Das Ändern von b's pick
zu squash
wird zu dem Fehler führen, den Sie gesehen haben, aber wenn Sie stattdessen c in b (neuer Commit in den älteren oder "nach oben squashen") verschmelzen, indem Sie die Todo-Liste ändern zu
pick b76d157 b
squash a931ac7 c
und Ihren Editor speichern und verlassen, erhalten Sie einen weiteren Editor, dessen Inhalt ist
# Dies ist eine Kombination aus 2 Commits.
# Die Nachricht des ersten Commits lautet:
b
# Das ist die Nachricht des 2. Commits:
c
Wenn Sie speichern und beenden, werden die Inhalte der bearbeiteten Datei zur Commit-Nachricht des neuen kombinierten Commits:
$ git log --pretty=oneline
18fd73d3ce748f2a58d1b566c03dd9dafe0b6b4f b und c
df239176e1a2ffac927d8b496ea00d5488481db5 a
Hinweis zur Neuschreibung der Historie
Die interaktive Neuabstimmung schreibt die Historie um. Ein Versuch, auf ein Remote zu pushen, das die alte Historie enthält, wird aufgrund mangelnder Fortschritte fehlschlagen.
Wenn der von Ihnen neu abgestimmte Zweig ein Thema- oder Feature-Zweig ist, an dem Sie alleine arbeiten, ist das kein großes Problem. Das Pushen zu einem anderen Repository erfordert die --force
-Option, oder alternativ können Sie, abhängig von den Berechtigungen des Remote-Repositorys, zunächst den alten Zweig löschen und dann die abgestimmte Version pushen. Beispiele für diese Befehle, die potenziell Arbeit zerstören können, sind nicht Teil dieser Antwort.
Das Neuschreiben bereits veröffentlichter Historie auf einem Zweig, an dem Sie mit anderen Personen arbeiten, ohne einen sehr guten Grund wie das Preisgeben eines Passworts oder anderer sensibler Details, zwingt Arbeit auf Ihre Mitarbeiter und ist antisozial und wird andere Entwickler verärgern. Der Abschnitt "Erholung von einem Upstream-Rebase" im git rebase
-Dokument erklärt das ausführlicher.
Einen Zweig neu zu basieren (oder auf eine andere Weise neu zu schreiben), der von anderen zur Arbeit genutzt wird, ist keine gute Idee: Jeder, der davon abhängig ist, muss ihre Historie manuell reparieren. Dieser Abschnitt erklärt, wie die Reparatur aus Sicht des Abhängigen erfolgt. Die eigentliche Lösung wäre jedoch, den Upstream-Rebase im ersten Schritt zu vermeiden. …