Update Juli 2012 ( git 1.7.12+ )
Sie können nun alle Commits bis zu Root zurücksetzen und den zweiten Commit auswählen Y
mit dem ersten zu zerquetschen X
.
git rebase -i --root master
pick sha1 X
squash sha1 Y
pick sha1 Z
git rebase [-i] --root $tip
Dieser Befehl kann nun verwendet werden, um den gesamten Verlauf von " $tip
"bis hin zur Root-Übertragung.
Ver commit df5df20c1308f936ea542c86df1e9c6974168472 auf GitHub von Chris Webb ( arachsys
) .
Wie bereits erwähnt in den Kommentaren , a git push --force-with-lease
(Sicherer als --force
als Mikko Mantalainen uns erinnern ) wäre nach jeder rebase
Operation, wenn Sie die Überarbeitung in einem entfernten Repository veröffentlichen müssen.
Originalantwort (Februar 2009)
Ich glaube, Sie finden verschiedene Rezepte dafür in der SO-Frage " Wie kombiniere ich die ersten beiden Commits eines Git-Repositorys? "
Charles Bailey sofern dort die meisten ausführliche Antwort und erinnert uns daran, dass ein Commit ein vollständiger Baum ist (nicht nur die Unterschiede zu einem früheren Zustand).
Und hier haben der alte Commit (der "ursprüngliche Commit") und der neue Commit (das Ergebnis der Zerschlagung) keinen gemeinsamen Vorfahren.
Das heißt, Sie können nicht " commit --amend
"die ursprüngliche Übergabe in eine neue Übergabe umwandeln und dann die Historie der vorherigen ursprünglichen Übergabe auf die neue Übergabe umbinden (viele Konflikte)
(Der letzte Satz gilt nicht mehr für git rebase -i --root <aBranch>
)
Vielmehr (mit A
die ursprüngliche "ursprüngliche Übergabe", und B
eine nachfolgende Übertragung musste in die erste eingefügt werden):
-
Gehen Sie zurück zum letzten Commit, das den ersten Commit bilden soll (HEAD abtrennen):
git checkout <sha1_for_B>
-
Setzt den Zweigzeiger auf die ursprüngliche Übergabe zurück, lässt aber den Index und den Arbeitsbaum intakt:
git reset --soft <sha1_for_A>
-
Ändern Sie den ursprünglichen Baum mit Hilfe des Baums aus 'B':
git commit --amend
-
Markieren Sie vorübergehend diesen neuen ersten Commit (oder merken Sie sich den neuen Commit sha1 manuell):
git tag tmp
-
Gehen Sie zurück zum ursprünglichen Zweig (nehmen Sie für dieses Beispiel master an):
git checkout master
-
Alle Übertragungen nach B werden auf die neue ursprüngliche Übertragung übertragen:
git rebase --onto tmp <sha1_for_B>
-
Entfernen Sie die temporäre Markierung:
git tag -d tmp
Auf diese Weise wird die " rebase --onto
"führt nicht zu Konflikten während des Zusammenführens, da es die Historie neu berechnet gemacht nach die letzte Übertragung ( B
), die in die ursprüngliche (d.h. A
) an tmp
(repräsentiert die zerquetschte neue ursprüngliche Übergabe): nur triviale Schnellzusammenführungen.
Das funktioniert für " A-B
", aber auch " A-...-...-...-B
"(eine beliebige Anzahl von Übertragungen kann auf diese Weise in die erste Übertragungen gequetscht werden)
0 Stimmen
Verwandt: Den Root-Commit in Git bearbeiten? .
0 Stimmen
Einzeiler:
git squash 2
mit dem Aliassquash = !"f() { NL=$1; GIT_EDITOR=\"sed -i '2,$NL s/pick/squash/;/# This is the 2nd commit message:/,$ {d}'\"; git rebase -i HEAD~$NL; }; f"
. Siehe stackoverflow.com/a/28789349/670229 .1 Stimmen
Das Skript "squash": Bei zwei Commits existiert der HEAD~2, den dieses Skript erzeugt, nicht, so dass es in diesem einen speziellen Fall nicht funktioniert.