Angenommen, ich habe den folgenden Commit-Verlauf in meinem Zweig nur vor Ort:
A -- B -- C
Wie füge ich ein neues Commit zwischen Aund ein B?
Angenommen, ich habe den folgenden Commit-Verlauf in meinem Zweig nur vor Ort:
A -- B -- C
Wie füge ich ein neues Commit zwischen Aund ein B?
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 Sie pickin Ihrem Editor für diese Zeile in edit.a1b2c3d), als wäre es gerade festgeschrieben worden .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.
A -- B -- C -- Dstatt gewünscht A -- D -- B -- C.
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 B pickLinien, legen wir eine neue pick 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.
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).
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:
git rebase temp branch
(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:
git branch -d temp
Danach sieht der Verlauf wie folgt aus:
A -- N -- B -- C
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.
git push --forcedas Remote-Repo ändern.
git rebase temp branch -Xtheirs. Hilfreiche Antwort zum Einfügen in ein Skript!
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.
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
pick 74096b9 D
pick 8668d21 B
pick 650f1fc C
Jetzt haben Sie:
A -- D -- B -- C
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.
break
pick <B's hash> <B's commit message>
pick <C's hash> <C's commit message>
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.
rebasehier. 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
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.