1285 Stimmen

Wie kann ich zwei Commits zu einem zusammenführen, wenn ich bereits einen Rebase gestartet habe?

Ich versuche, 2 Commits zu einem zusammenzuführen, also habe ich "Commits mit Rebase zusammenführen" von Git ready befolgt.

Ich habe ausgeführt

git rebase --interactive HEAD~2

In dem resultierenden Editor ändere ich pick zu squash und speichere und beende dann, aber der Rebase schlägt fehl mit dem Fehler

Kann nicht 'squash' ohne einen vorherigen Commit

Jetzt, da mein Arbeitsverzeichnis diesen Zustand erreicht hat, habe ich Probleme, mich zu erholen.

Der Befehl git rebase --interactive HEAD~2 schlägt fehl mit:

Interaktiver Rebase bereits gestartet

und git rebase --continue schlägt fehl mit

Kann nicht 'squash' ohne einen vorherigen Commit

1887voto

Greg Bacon Punkte 127209

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.

473voto

user3828059 Punkte 4731

Wenn es mehrere Commits gibt, können Sie git rebase -i verwenden, um zwei Commits zu einem zusammenzufassen.

Wenn es nur zwei Commits gibt, die Sie zusammenführen möchten und sie die "zwei aktuellsten" sind, können die folgenden Befehle verwendet werden, um die beiden Commits zu kombinieren:

git reset --soft "HEAD^"
git commit --amend

169voto

pambda Punkte 2590

Rebase: You Ain't Gonna Need It:

Ein simpler Weg für das häufigste Szenario.

In den meisten Fällen:

Eigentlich, wenn alles was du willst ist, einfach mehrere kürzliche Commits zu einem zu kombinieren, aber keine drop, reword und andere Rebase-Arbeit benötigst.

du kannst einfach tun:

git reset --soft "HEAD~n"
  • Angenommen, ~n ist die Anzahl der Commits, die sanft zurückgenommen werden sollen (d.h. ~1, ~2,...)

Verwende dann folgenden Befehl, um die Commit-Nachricht zu ändern.

git commit --amend

was im Wesentlichen dasselbe ist wie eine lange Reihe von squash und einem pick.

Und es funktioniert für n Commits, nicht nur für zwei Commits wie in der oben genannten Antwort.

59voto

Haimei Punkte 11915

Zuerst sollten Sie überprüfen, wie viele Commits Sie haben:

git log

Es gibt zwei Zustände:

Ein Zustand ist, dass es nur zwei Commits gibt:

Zum Beispiel:

Commit A
Commit B

(In diesem Fall können Sie git rebase nicht verwenden) Sie müssen Folgendes tun.

$ git reset --soft HEAD^1

$ git commit --amend

Ein anderer Zustand ist, dass es mehr als zwei Commits gibt und Sie den Commit C und D zusammenführen möchten.

Zum Beispiel:

Commit A
Commit B
Commit C
Commit D

(unter dieser Bedingung können Sie git rebase verwenden)

git rebase -i B

Und dann verwenden Sie "squash", um es zu tun. Der Rest ist sehr einfach. Wenn Sie immer noch nicht wissen, lesen Sie bitte http://zerodie.github.io/blog/2012/01/19/git-rebase-i/

45voto

Homan Punkte 24348

Vorausgesetzt, Sie waren in Ihrem eigenen Themenzweig. Wenn Sie die letzten 2 Commits zusammenführen und wie ein Held aussehen möchten, verzweigen Sie vom Commit direkt vor den letzten beiden Commits ab (angegeben mit dem relativen Commit-Namen HEAD~2).

git checkout -b temp_branch HEAD~2

Dann squashe den anderen Branch in diesem neuen Branch:

git merge branch_with_two_commits --squash

Dadurch werden die Änderungen übernommen, aber nicht committet. Committen Sie sie einfach und fertig.

git commit -m "meine Nachricht"

Jetzt können Sie diesen neuen Themenzweig wieder in Ihren Hauptzweig mergen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X