Ich habe meine Geschichte durcheinander gebracht und möchte einige Änderungen daran vornehmen. Das Problem ist, dass ich ein Commit mit zwei nicht zusammenhängenden Änderungen habe und dieses Commit von einigen anderen Änderungen in meinem lokalen (nicht gepushen) Verlauf umgeben ist.
Ich möchte dieses Commit aufteilen, bevor ich es herausbringe, aber die meisten Anleitungen, die ich sehe, haben mit dem Aufteilen Ihres letzten Commits oder nicht festgeschriebenen lokalen Änderungen zu tun. Ist es möglich, dies für ein Commit zu tun, das ein wenig in der Geschichte vergraben ist, ohne meine Commits seitdem erneut ausführen zu müssen?
Antworten:
In der Rebase-Manpage finden Sie eine Anleitung zum Aufteilen von Commits . Die kurze Zusammenfassung lautet:
Führen Sie eine interaktive Rebase mit dem Ziel-Commit (z. B.
git rebase -i <commit-to-split>^ branch
) durch und markieren Sie es als zu bearbeitend.Wenn die Rebase dieses Commit erreicht, verwenden Sie diese Option, um
git reset HEAD^
sie vor dem Commit zurückzusetzen. Behalten Sie jedoch Ihren Arbeitsbaum bei.Fügen Sie schrittweise Änderungen hinzu und schreiben Sie sie fest, wobei Sie so viele Festschreibungen wie gewünscht vornehmen.
add -p
kann nützlich sein, um nur einige der Änderungen in einer bestimmten Datei hinzuzufügen. Verwendencommit -c ORIG_HEAD
Sie diese Option, wenn Sie die ursprüngliche Festschreibungsnachricht für eine bestimmte Festschreibung erneut verwenden möchten.Wenn Sie testen möchten, was Sie festschreiben (gute Idee!)
git stash
, Um den Teil zu verbergen, den Sie nicht festgeschrieben haben (oderstash --keep-index
bevor Sie ihn überhaupt festschreiben), testen Sie undgit stash pop
geben Sie den Rest an den Arbeitsbaum zurück. Machen Sie so lange Commits, bis Sie alle Änderungen festgeschrieben haben, dh einen sauberen Arbeitsbaum haben.Führen Sie
git rebase --continue
diese Option aus, um die Commits nach dem jetzt aufgeteilten Commit anzuwenden.quelle
git rebase -i <sha1_of_the_commit_to_split>^ branch
. Undgit gui
ist ein nettes Tool für die Aufteilungsaufgabe, mit dem verschiedene Teile einer Datei zu verschiedenen Commits hinzugefügt werden können.git add -p
, was mehrgit gui
kann als in dieser Abteilung (insbesondere das Bearbeiten von Hunks, das Staging von allem ab dem aktuellen Hunk und das Suchen nach Hunks durch Regex).So geht's mit Magit .
Angenommen, Commit ed417ae ist dasjenige, das Sie ändern möchten. Es enthält zwei nicht zusammenhängende Änderungen und ist unter einem oder mehreren Commits begraben. Hit
ll
das Protokoll zu zeigen, und navigieren Sie zu ed417ae:r
Drücken Sie dann , um das Rebase-Popup zu öffnenund
m
um das Commit am Punkt zu ändern.Beachten Sie, wie sich das
@
Commit jetzt aufteilt, das Sie teilen möchten. Dies bedeutet, dass sich HEAD jetzt bei diesem Commit befindet:Wir möchten HEAD auf das übergeordnete Element verschieben. Navigieren Sie also zum übergeordneten Element (47e18b3), drücken Sie
x
(magit-reset-quickly
gebunden an,o
wenn Sie es verwendenevil-magit
) und geben Sie "Ja, ich meinte Festschreiben an Punkt" ein. Ihr Protokoll sollte nun folgendermaßen aussehen:Nun traf
q
zum regulären Magit Status zu gehen, verwenden Sie dann den regulären unstageu
Befehl unstage was nicht in geht das erste zu begehen, zu begehen ,c
den Rest wie üblich, danns
tage undc
ommit was geht das zweite begehen, und wenn Sie fertig sind : treffenr
die rebase Popup zu öffnenund noch eine,
r
um fortzufahren, und du bist fertig!ll
zeigt jetzt:quelle
Um ein Commit aufzuteilen
<commit>
und das neue Commit vor diesem hinzuzufügen und das Autorendatum von zu speichern, gehen Sie<commit>
wie folgt vor:Bearbeiten Sie das Commit zuvor
<commit>
NB: Vielleicht muss es auch bearbeitet
<commit>
werden.Kirsche
<commit>
in den Index holenSetzen Sie nicht benötigte Änderungen aus dem Index interaktiv zurück und setzen Sie den Arbeitsbaum zurück
Als Alternative können Sie nicht benötigte Änderungen interaktiv aufbewahren:
git stash push -p -m "tmp other changes"
Nehmen Sie weitere Änderungen vor (falls vorhanden) und erstellen Sie das neue Commit
Wiederholen Sie optional die Punkte 2 bis 4, um weitere Zwischen-Commits hinzuzufügen.
Setzen Sie die Neubasierung fort
quelle
Es gibt eine schnellere Version, wenn Sie nur Inhalte aus nur einer Datei extrahieren möchten. Es ist schneller, weil die interaktive Rebase nicht mehr interaktiv ist (und es ist natürlich noch schneller, wenn Sie aus dem letzten Commit extrahieren möchten, dann müssen Sie überhaupt keine Rebase mehr erstellen).
the_file
. Schließenthe_file
. Dies ist die einzige Edition, die Sie benötigen. Der Rest sind nur Git-Befehle.Stellen Sie diese Löschung im Index bereit:
Stellen Sie die gerade gelöschten Zeilen wieder in der Datei wieder her, ohne den Index zu beeinflussen !
"SHA1" ist das Commit, aus dem Sie die Zeilen extrahieren möchten:
Erstellen Sie das zweite brandneue Commit mit dem zu extrahierenden Inhalt, der in Schritt 3 wiederhergestellt wurde:
Nicht bearbeiten, nicht anhalten / fortfahren - einfach alles akzeptieren:
Natürlich noch schneller, wenn das Commit, aus dem extrahiert werden soll, das letzte Commit ist:
Wenn Sie verwenden, sind
magit
Schritt 4, 5 und 6 eine einzelne Aktion: Festschreiben, sofortige Korrekturquelle
Wenn Sie noch nicht gedrückt haben, verwenden Sie einfach
git rebase
. Noch besser istgit rebase -i
es, Commits interaktiv zu verschieben. Sie können das fehlerhafte Commit nach vorne verschieben, es dann nach Belieben aufteilen und die Patches nach hinten verschieben (falls erforderlich).quelle