git rebase -i <any earlier commit>. Dies zeigt eine Liste der Commits in Ihrem konfigurierten Texteditor an.
Suchen Sie das Commit, nach dem Sie einfügen möchten (nehmen wir an, es ist a1b2c3d). Ändern Sie pickin Ihrem Editor für diese Zeile in edit.
Beginnen Sie die Rebase, indem Sie Ihren Texteditor schließen (speichern Sie Ihre Änderungen). Dadurch bleiben Sie an einer Eingabeaufforderung mit dem zuvor ausgewählten Commit ( a1b2c3d), als wäre es gerade festgeschrieben worden .
Nehmen Sie Ihre Änderungen vor und git commit( NICHT im Gegensatz zu den meisten anderen edit). Dadurch wird nach dem von Ihnen ausgewählten Commit ein neues Commit erstellt .
git rebase --continue. Dadurch werden die aufeinanderfolgenden Commits wiederholt, und Ihr neues Commit wird an der richtigen Stelle eingefügt.
Beachten Sie, dass dies die Geschichte neu schreibt und jeden anderen bricht, der versucht zu ziehen.
Dies fügte das neue Commit nach dem Commit hinzu, dh nach dem, auf das ich neu basiert (auch das letzte Commit), anstatt direkt nach dem, auf das ich neu basiert habe. Das Ergebnis war das gleiche, als hätte ich am Ende einfach ein neues Commit mit den Änderungen vorgenommen, die ich einfügen wollte. Meine Geschichte wurde A -- B -- C -- Dstatt gewünscht A -- D -- B -- C.
XedinUnknown
2
@XedinUnknown: Dann haben Sie Rebase nicht richtig verwendet.
SLaks
3
Jetzt Dkönnte überall ein Commit sein. Nehmen wir an, wir haben A - B - Cund wir haben ein Commit, Ddas nicht einmal in diesem Zweig ist. Wir wissen, dass es SHA ist, aber wir können es tun git rebase -i HEAD~3. Jetzt zwischen den Aund BpickLinien, legen wir eine neuepick Linie , die sagt pick SHA, den Hash des gewünschten geben D. Es muss nicht der vollständige Hash sein, sondern nur der verkürzte. git rebase -iNur Cherry wählt die Commits aus, die durch pickZeilen im Puffer aufgelistet sind . Sie müssen nicht die Originale sein, die für Sie aufgelistet sind.
Kaz
1
@Kaz Das sieht nach einer anderen, gültigen Antwort aus.
BartoszKP
3
Noch einfacher ist es, das breakSchlüsselwort im Editor in einer eigenen Zeile zwischen zwei Commits zu verwenden (oder in der ersten Zeile, um ein Commit vor dem angegebenen Commit einzufügen).
SimonT
30
Es stellt sich als recht einfach heraus, die Antwort hier zu finden . Angenommen, Sie befinden sich in einem Zweig branch. Führen Sie die folgenden Schritte aus:
Erstellen Sie einen temporären Zweig aus dem Commit, nachdem Sie das neue Commit einfügen möchten (in diesem Fall Commit A):
git checkout -b temp A
Führen Sie die Änderungen durch und schreiben Sie sie fest. Erstellen Sie ein Commit. Nennen wir es N:
git commit -a -m "Message"
(oder git addgefolgt von git commit)
Basen Sie die Commits, die Sie nach dem neuen Commit (in diesem Fall Commits Bund C) haben möchten, auf das neue Commit zurück:
Ich konnte der akzeptierten Antwort von SLaks nicht folgen, aber das funktionierte für mich. Nachdem ich den gewünschten Commit-Verlauf erhalten hatte, musste ich git push --forcedas Remote-Repo ändern.
Fluchtzeichen
1
Wenn Sie rebase mit der Option -Xtheirs verwenden, werden Konflikte automatisch korrekt gelöst git rebase temp branch -Xtheirs. Hilfreiche Antwort zum Einfügen in ein Skript!
David C
Für Noobs wie mich möchte ich das nachher hinzufügen git rebase temp branch, aber vorher git branch -d tempmüssen Sie nur Konflikte und Probleme beheben und inszenieren git rebase --continue, dh Sie müssen nichts begehen usw.
Pugsley
19
Noch einfachere Lösung:
Erstellen Sie am Ende Ihr neues Commit, D. Jetzt haben Sie:
A -- B -- C -- D
Dann renne:
$ git rebase -i hash-of-A
Git öffnet Ihren Editor und sieht folgendermaßen aus:
pick 8668d21 B
pick 650f1fc C
pick 74096b9 D
Bewegen Sie D einfach so nach oben, speichern Sie es und beenden Sie es
Gute Idee, aber es kann schwierig sein, D auf C einzuführen, wenn Sie beabsichtigen, diese Änderungen vorzunehmen. an A.
BartoszKP
Ich habe eine Situation, in der ich 3 Commits habe, die ich zusammen neu aufbauen möchte, und ein Commit in der Mitte, das nichts damit zu tun hat. Dies ist super schön, wenn Sie dieses Commit früher oder später in der Reihe der Commits verschieben können.
Unflores
13
Angenommen, der Commit-Verlauf lautet wie folgt: preA -- A -- B -- CWenn Sie einen Commit zwischen Aund einfügen möchten, Blauten die Schritte wie folgt:
git rebase -i hash-of-preA
Git öffnet Ihren Editor. Der Inhalt könnte folgendermaßen aussehen:
pick 8668d21 A
pick 650f1fc B
pick 74096b9 C
Ändern Sie die erste pickin edit:
edit 8668d21 A
pick 650f1fc B
pick 74096b9 C
Speichern und schließen.
Ändern Sie Ihren Code und dann git add . && git commit -m "I"
git rebase --continue
Jetzt ist Ihr Git-Commit-Verlauf preA -- A -- I -- B -- C
Wenn Sie auf einen Konflikt stoßen, stoppt Git bei diesem Commit. Sie können git diffKonfliktmarkierungen suchen und lösen. Nachdem Sie alle Konflikte git add <filename>gelöst haben , müssen Sie Git mitteilen, dass der Konflikt gelöst wurde, und anschließend erneut ausführen git rebase --continue.
Wenn Sie die Rebase rückgängig machen möchten, verwenden Sie git rebase --abort.
Hier ist eine Strategie, die es vermeidet, während der Rebase einen "Edit-Hack" durchzuführen, wie in den anderen Antworten zu sehen ist, die ich gelesen habe.
Durch die Verwendung erhalten git rebase -iSie eine Liste der Commits seit diesem Commit. Fügen Sie einfach oben in der Datei einen "break" hinzu. Dadurch wird die Rebase an diesem Punkt unterbrochen.
Einmal gestartet, git rebasestoppt nun an der Stelle der "Pause". Sie können jetzt Ihre Dateien bearbeiten und Ihr Commit normal erstellen. Sie können dann die Rebase mit fortsetzen git rebase --continue. Dies kann zu Konflikten führen, die Sie beheben müssen. Wenn Sie sich verlaufen, vergessen Sie nicht, dass Sie jederzeit mit abbrechen können git rebase --abort.
Diese Strategie kann verallgemeinert werden, um ein Commit an einer beliebigen Stelle einzufügen. Setzen Sie einfach die "Pause" an die Stelle, an der Sie ein Commit einfügen möchten.
Vergessen Sie nicht, nach dem Umschreiben der Geschichte git push -f. Es gelten die üblichen Warnungen vor anderen Personen, die Ihre Filiale abrufen.
Entschuldigung, aber ich habe Probleme zu verstehen, wie dies "Vermeiden von Rebase" ist. Sie werden laufen rebasehier. Es ist kein großer Unterschied, ob Sie das Commit während der Rebase oder im Voraus erstellen.
BartoszKP
Woops, ich wollte den "Edit Hack" während der Rebase vermeiden, ich denke, ich habe das schlecht formuliert.
Axerologementy
Richtig. Meine Antwort verwendet auch nicht die "Bearbeiten" -Funktion von Rebase. Dies ist jedoch ein weiterer gültiger Ansatz - danke! :-)
BartoszKP
6
Viele gute Antworten hier schon. Ich wollte nur eine "No Rebase" -Lösung in 4 einfachen Schritten hinzufügen.
Zusammenfassung
git checkout A
git commit -am "Message for commit D"
git cherry-pick A..C
git branch -f master HEAD
Erläuterung
(Hinweis: Ein Vorteil dieser Lösung besteht darin, dass Sie Ihren Zweig erst im letzten Schritt berühren, wenn Sie zu 100% sicher sind, dass Sie mit dem Endergebnis einverstanden sind, sodass Sie einen sehr praktischen Schritt zur "Vorbestätigung" haben AB-Tests zulassen .)
Ausgangszustand (ich habe masterfür Ihren Filialnamen angenommen )
A -- B -- C <<< master <<< HEAD
1) Richten Sie den KOPF zunächst auf die richtige Stelle
git checkout A
B -- C <<< master
/
A <<< detached HEAD
(Optional hätten wir hier anstelle von HEAD einen temporären Zweig erstellen können, mit git checkout -b temp Adem wir am Ende des Prozesses löschen müssten. Beide Varianten funktionieren nach Ihren Wünschen, da alles andere gleich bleibt.)
2) Erstellen Sie das neue Commit D, das eingefügt werden soll
# at this point, make the changes you wanted to insert between A and B, then
git commit -am "Message for commit D"
B -- C <<< master
/
A -- D <<< detached HEAD (or <<< temp <<< HEAD)
3) Bringen Sie dann Kopien der letzten fehlenden Commits B und C mit (wäre dieselbe Zeile, wenn es mehr Commits gäbe).
git cherry-pick A..C
# (if any, resolve any potential conflicts between D and these last commits)
B -- C <<< master
/
A -- D -- B' -- C' <<< detached HEAD (or <<< temp <<< HEAD)
(bequemer AB-Test hier bei Bedarf)
Jetzt ist der Moment gekommen, um Ihren Code zu überprüfen, alles zu testen, was getestet werden muss, und Sie können auch unterscheiden / vergleichen / überprüfen, was Sie hatten und was Sie nach den Operationen erhalten würden.
4) Abhängig von Ihren Tests zwischen Cund C'ist entweder OK oder KO.
(BEIDES) 4-OK) Bewegen Sie zum Schluss den Ref vonmaster
git branch -f master HEAD
B -- C <<< (B and C are candidates for garbage collection)
/
A -- D -- B' -- C' <<< master
(ODER) 4-KO) Einfach masterunverändert lassen
Wenn Sie einen temporären Zweig erstellt haben, löschen Sie ihn einfach mit git branch -d <name>. Wenn Sie sich jedoch für die getrennte HEAD-Route entschieden haben und zu diesem Zeitpunkt überhaupt keine Aktion erforderlich ist, können die neuen Commits unmittelbar nach dem erneuten Anhängen HEADmit a für die Speicherbereinigung verwendet werdengit checkout master
In beiden Fällen (OK oder KO) müssen Sie an dieser Stelle mastererneut auschecken, um die Verbindung wiederherzustellen HEAD.
Antworten:
Es ist noch einfacher als in der Antwort von OP.
git rebase -i <any earlier commit>
. Dies zeigt eine Liste der Commits in Ihrem konfigurierten Texteditor an.a1b2c3d
). Ändern Siepick
in Ihrem Editor für diese Zeile inedit
.a1b2c3d
), als wäre es gerade festgeschrieben worden .git commit
( NICHT im Gegensatz zu den meisten anderenedit
). Dadurch wird nach dem von Ihnen ausgewählten Commit ein neues Commit erstellt .git rebase --continue
. Dadurch werden die aufeinanderfolgenden Commits wiederholt, und Ihr neues Commit wird an der richtigen Stelle eingefügt.Beachten Sie, dass dies die Geschichte neu schreibt und jeden anderen bricht, der versucht zu ziehen.
quelle
A -- B -- C -- D
statt gewünschtA -- D -- B -- C
.D
könnte überall ein Commit sein. Nehmen wir an, wir habenA - B - C
und wir haben ein Commit,D
das nicht einmal in diesem Zweig ist. Wir wissen, dass es SHA ist, aber wir können es tungit rebase -i HEAD~3
. Jetzt zwischen denA
undB
pick
Linien, legen wir eine neuepick
Linie , die sagtpick SHA
, den Hash des gewünschten gebenD
. Es muss nicht der vollständige Hash sein, sondern nur der verkürzte.git rebase -i
Nur Cherry wählt die Commits aus, die durchpick
Zeilen im Puffer aufgelistet sind . Sie müssen nicht die Originale sein, die für Sie aufgelistet sind.break
Schlüsselwort im Editor in einer eigenen Zeile zwischen zwei Commits zu verwenden (oder in der ersten Zeile, um ein Commit vor dem angegebenen Commit einzufügen).Es stellt sich als recht einfach heraus, die Antwort hier zu finden . Angenommen, Sie befinden sich in einem Zweig
branch
. Führen Sie die folgenden Schritte aus:Erstellen Sie einen temporären Zweig aus dem Commit, nachdem Sie das neue Commit einfügen möchten (in diesem Fall Commit
A
):Führen Sie die Änderungen durch und schreiben Sie sie fest. Erstellen Sie ein Commit. Nennen wir es
N
:(oder
git add
gefolgt vongit commit
)Basen Sie die Commits, die Sie nach dem neuen Commit (in diesem Fall Commits
B
undC
) haben möchten, auf das neue Commit zurück:(Möglicherweise müssen Sie diese verwenden
-p
, um Zusammenführungen beizubehalten, falls vorhanden - dank eines nicht mehr vorhandenen Kommentars von ciekawy )Löschen Sie den temporären Zweig:
Danach sieht der Verlauf wie folgt aus:
Es ist natürlich möglich, dass beim erneuten Basieren einige Konflikte auftreten.
Wenn Ihre Niederlassung nicht nur lokal ist, führt dies zum Umschreiben des Verlaufs und kann daher zu ernsthaften Problemen führen.
quelle
git push --force
das Remote-Repo ändern.git rebase temp branch -Xtheirs
. Hilfreiche Antwort zum Einfügen in ein Skript!git rebase temp branch
, aber vorhergit branch -d temp
müssen Sie nur Konflikte und Probleme beheben und inszenierengit rebase --continue
, dh Sie müssen nichts begehen usw.Noch einfachere Lösung:
Erstellen Sie am Ende Ihr neues Commit, D. Jetzt haben Sie:
Dann renne:
Git öffnet Ihren Editor und sieht folgendermaßen aus:
Bewegen Sie D einfach so nach oben, speichern Sie es und beenden Sie es
Jetzt haben Sie:
quelle
Angenommen, der Commit-Verlauf lautet wie folgt:
preA -- A -- B -- C
Wenn Sie einen Commit zwischenA
und einfügen möchten,B
lauten die Schritte wie folgt:git rebase -i hash-of-preA
Git öffnet Ihren Editor. Der Inhalt könnte folgendermaßen aussehen:
Ändern Sie die erste
pick
inedit
:Speichern und schließen.
Ändern Sie Ihren Code und dann
git add . && git commit -m "I"
git rebase --continue
Jetzt ist Ihr Git-Commit-Verlauf
preA -- A -- I -- B -- C
Wenn Sie auf einen Konflikt stoßen, stoppt Git bei diesem Commit. Sie können
git diff
Konfliktmarkierungen suchen und lösen. Nachdem Sie alle Konfliktegit add <filename>
gelöst haben , müssen Sie Git mitteilen, dass der Konflikt gelöst wurde, und anschließend erneut ausführengit rebase --continue
.Wenn Sie die Rebase rückgängig machen möchten, verwenden Sie
git rebase --abort
.quelle
Hier ist eine Strategie, die es vermeidet, während der Rebase einen "Edit-Hack" durchzuführen, wie in den anderen Antworten zu sehen ist, die ich gelesen habe.
Durch die Verwendung erhalten
git rebase -i
Sie eine Liste der Commits seit diesem Commit. Fügen Sie einfach oben in der Datei einen "break" hinzu. Dadurch wird die Rebase an diesem Punkt unterbrochen.Einmal gestartet,
git rebase
stoppt nun an der Stelle der "Pause". Sie können jetzt Ihre Dateien bearbeiten und Ihr Commit normal erstellen. Sie können dann die Rebase mit fortsetzengit rebase --continue
. Dies kann zu Konflikten führen, die Sie beheben müssen. Wenn Sie sich verlaufen, vergessen Sie nicht, dass Sie jederzeit mit abbrechen könnengit rebase --abort
.Diese Strategie kann verallgemeinert werden, um ein Commit an einer beliebigen Stelle einzufügen. Setzen Sie einfach die "Pause" an die Stelle, an der Sie ein Commit einfügen möchten.
Vergessen Sie nicht, nach dem Umschreiben der Geschichte
git push -f
. Es gelten die üblichen Warnungen vor anderen Personen, die Ihre Filiale abrufen.quelle
rebase
hier. Es ist kein großer Unterschied, ob Sie das Commit während der Rebase oder im Voraus erstellen.Viele gute Antworten hier schon. Ich wollte nur eine "No Rebase" -Lösung in 4 einfachen Schritten hinzufügen.
Zusammenfassung
Erläuterung
(Hinweis: Ein Vorteil dieser Lösung besteht darin, dass Sie Ihren Zweig erst im letzten Schritt berühren, wenn Sie zu 100% sicher sind, dass Sie mit dem Endergebnis einverstanden sind, sodass Sie einen sehr praktischen Schritt zur "Vorbestätigung" haben AB-Tests zulassen .)
Ausgangszustand (ich habe
master
für Ihren Filialnamen angenommen )1) Richten Sie den KOPF zunächst auf die richtige Stelle
(Optional hätten wir hier anstelle von HEAD einen temporären Zweig erstellen können, mit
git checkout -b temp A
dem wir am Ende des Prozesses löschen müssten. Beide Varianten funktionieren nach Ihren Wünschen, da alles andere gleich bleibt.)2) Erstellen Sie das neue Commit D, das eingefügt werden soll
3) Bringen Sie dann Kopien der letzten fehlenden Commits B und C mit (wäre dieselbe Zeile, wenn es mehr Commits gäbe).
(bequemer AB-Test hier bei Bedarf)
Jetzt ist der Moment gekommen, um Ihren Code zu überprüfen, alles zu testen, was getestet werden muss, und Sie können auch unterscheiden / vergleichen / überprüfen, was Sie hatten und was Sie nach den Operationen erhalten würden.
4) Abhängig von Ihren Tests zwischen
C
undC'
ist entweder OK oder KO.(BEIDES) 4-OK) Bewegen Sie zum Schluss den Ref von
master
(ODER) 4-KO) Einfach
master
unverändert lassenWenn Sie einen temporären Zweig erstellt haben, löschen Sie ihn einfach mit
git branch -d <name>
. Wenn Sie sich jedoch für die getrennte HEAD-Route entschieden haben und zu diesem Zeitpunkt überhaupt keine Aktion erforderlich ist, können die neuen Commits unmittelbar nach dem erneuten AnhängenHEAD
mit a für die Speicherbereinigung verwendet werdengit checkout master
In beiden Fällen (OK oder KO) müssen Sie an dieser Stelle
master
erneut auschecken, um die Verbindung wiederherzustellenHEAD
.quelle