Ist es möglich, ein einzelnes Commit in ein paar verschiedene Commits zu unterteilen, nachdem es in das lokale Repository festgeschrieben wurde, ohne einen Zweig zu erstellen und eine Menge Funky-Arbeit an einem neuen Zweig zu leisten?
1224
git autorebase split COMMIT_ID
git reset HEAD~
,git stash
, danngit cherry-pick
die erste innerhalb des Squash begehen, danngit stash pop
. Mein cherry-pick Fall ist ganz spezifisch hier, abergit stash
undgit stash pop
ist für andere ganz praktisch.Antworten:
git rebase -i
werde es tun.Beginnen Sie zunächst mit einem sauberen Arbeitsverzeichnis: Es
git status
sollten keine ausstehenden Änderungen, Löschungen oder Ergänzungen angezeigt werden.Jetzt müssen Sie entscheiden, welche Commits Sie teilen möchten.
A) Aufteilen des letzten Commits
Um Ihr letztes Commit aufzuteilen, gehen Sie zunächst wie folgt vor:
Legen Sie nun die Teile wie gewohnt einzeln fest und erstellen Sie so viele Festschreibungen, wie Sie benötigen.
B) Ein Commit weiter hinten aufteilen
Dies erfordert ein erneutes Basieren , dh ein Umschreiben des Verlaufs. Um das richtige Commit zu finden, haben Sie mehrere Möglichkeiten:
Wenn es drei Commits waren, dann
Wo
3
ist, wie viele Commits es zurück gibt?Wenn es weiter hinten im Baum war, als Sie zählen möchten, dann
Wo
123abcd
ist der SHA1 des Commits, den Sie aufteilen möchten?Wenn Sie sich in einem anderen Zweig befinden (z. B. einem Feature-Zweig), den Sie in den Master einbinden möchten:
Wenn Sie den Rebase-Bearbeitungsbildschirm erhalten, suchen Sie das Commit, das Sie trennen möchten. Am Anfang der Zeile, ersetzt
pick
mitedit
(e
kurz). Speichern Sie den Puffer und beenden Sie ihn. Rebase wird jetzt unmittelbar nach dem Commit gestoppt, das Sie bearbeiten möchten. Dann:Legen Sie die Teile wie gewohnt einzeln fest und produzieren Sie dann so viele Commits, wie Sie benötigen
quelle
git rebase --continue
, ich hatte tatsächlich zugit add (files to be added)
,git commit
und danngit stash
(für die restlichen Dateien). Danach habegit rebase --continue
ichgit checkout stash .
die restlichen Dateien erhaltengit add -p
diee
Möglichkeit nutzen, nur Teilabschnitte von Dateien hinzuzufügen, möglicherweise mit der Option, Unterschiede zu bearbeiten, um nur einen Teil eines Teils festzuschreiben.git stash
Dies ist auch nützlich, wenn Sie einige Arbeiten fortsetzen, diese jedoch aus dem aktuellen Commit entfernen möchten.git rebase -i HEAD^3
Befehl separat neu anordnen . Auf diese Weise müssen Sie nicht so viel Arbeit rückgängig machen, wenn die Aufteilung schlecht wird.git reset HEAD~
. Sie sind nicht verloren.Aus dem Git-Rebase- Handbuch (Abschnitt SPLITTING COMMITS)
quelle
~
statt^
.reset
das Commit - Nachricht enthalten. Wenn Sie wissen, dass Sie ein Commit aufteilen, aber einen Teil oder die gesamte Nachricht behalten möchten, sollten Sie eine Kopie dieser Nachricht erstellen. Also,git show
das Commit vor demrebase
Ing, oder wenn Sie dies vergessen oder bevorzugen: kommen Sie später über das zurückreflog
. Nichts davon wird tatsächlich "verloren" gehen, bis es in 2 Wochen oder was auch immer Müll gesammelt hat.~
und^
sind verschiedene Dinge, auch unter Windows. Sie wollen immer noch das Caret^
, also müssen Sie es nur entsprechend Ihrer Muschel entkommen. In PowerShell ist esHEAD`^
. Mit cmd.exe können Sie es verdoppeln, um wie zu entkommenHEAD^^
. In den meisten (allen?) Muscheln können Sie mit Anführungszeichen wie umgeben"HEAD^"
.git commit --reuse-message=abcd123
. Die kurze Option dafür ist-C
.Verwenden Sie
git rebase --interactive
diese Option, um das frühere Commit zu bearbeiten, auszuführengit reset HEAD~
und danngit add -p
einige hinzuzufügen, dann ein Commit durchzuführen, dann weitere hinzuzufügen und ein weiteres Commit durchzuführen, so oft Sie möchten. Wenn Sie fertig sind, führen Sie ausgit rebase --continue
, und Sie haben alle geteilten Commits früher in Ihrem Stapel.Wichtig : Beachten Sie, dass Sie herumspielen und alle gewünschten Änderungen vornehmen können und sich keine Sorgen machen müssen, alte Änderungen zu verlieren, da Sie jederzeit
git reflog
den Punkt in Ihrem Projekt finden können, der die gewünschten Änderungen enthält (nennen wir esa8c4ab
). und danngit reset a8c4ab
.Hier ist eine Reihe von Befehlen, um zu zeigen, wie es funktioniert:
mkdir git-test; cd git-test; git init
Fügen Sie nun eine Datei hinzu
A
vi A
füge diese Zeile hinzu:
one
git commit -am one
Fügen Sie dann diese Zeile zu A hinzu:
two
git commit -am two
Fügen Sie dann diese Zeile zu A hinzu:
three
git commit -am three
Jetzt sieht die Datei A folgendermaßen aus:
und unser
git log
sieht wie folgt aus (naja, ich benutzegit log --pretty=oneline --pretty="%h %cn %cr ---- %s"
Angenommen, wir möchten das zweite Commit aufteilen
two
.git rebase --interactive HEAD~2
Daraufhin wird eine Meldung angezeigt, die folgendermaßen aussieht:
Ändern Sie die erste
pick
in einee
, um dieses Commit zu bearbeiten.git reset HEAD~
git diff
zeigt uns, dass wir gerade das Commit aufgehoben haben, das wir für das zweite Commit gemacht haben:Lassen Sie uns diese Änderung inszenieren und dieser Zeile in der Datei "und ein Drittel" hinzufügen
A
.git add .
Dies ist normalerweise der Punkt während einer interaktiven Rebase, an dem wir ausgeführt werden
git rebase --continue
, da wir normalerweise nur in unseren Stapel von Commits zurückkehren möchten, um ein früheres Commit zu bearbeiten. Aber dieses Mal wollen wir ein neues Commit erstellen. Also rennen wirgit commit -am 'two and a third'
. Jetzt bearbeiten wir die DateiA
und fügen die Zeile hinzutwo and two thirds
.git add .
git commit -am 'two and two thirds'
git rebase --continue
Wir haben einen Konflikt mit unserem Commit
three
. Lösen wir ihn also:Wir werden uns ändern
zu
git add .; git rebase --continue
Jetzt
git log -p
sieht unser so aus:quelle
In früheren Antworten wurde die Verwendung von
git rebase -i
zum Bearbeiten des Commits, das Sie teilen möchten, und zum Festschreiben in Teilen behandelt.Dies funktioniert gut, wenn Sie die Dateien in verschiedene Commits aufteilen. Wenn Sie jedoch Änderungen an den einzelnen Dateien aufteilen möchten, müssen Sie mehr wissen.
Nachdem Sie das Commit erreicht haben, für das Sie es teilen, verwenden
rebase -i
und markieren möchtenedit
, haben Sie zwei Möglichkeiten.Nach der Verwendung
git reset HEAD~
, gehen Sie durch die Patches einzeln übergit add -p
diejenigen auszuwählen , die Sie in jeder wollen begehenBearbeiten Sie die Arbeitskopie, um die nicht gewünschten Änderungen zu entfernen. diesen Zwischenstaat begehen; und dann das volle Commit für die nächste Runde zurückziehen.
Option 2 ist nützlich, wenn Sie ein großes Commit aufteilen, da Sie überprüfen können, ob die Zwischenversionen im Rahmen der Zusammenführung ordnungsgemäß erstellt und ausgeführt werden. Dies läuft wie folgt ab.
Verwenden Sie nach dem Verwenden
rebase -i
undedit
Festlegen des CommitsUm das Festschreiben rückgängig zu machen, belassen Sie die festgeschriebenen Dateien jedoch im Index. Sie können auch einen gemischten Reset durchführen, indem Sie --soft weglassen, je nachdem, wie nahe das endgültige Ergebnis Ihres anfänglichen Commits sein wird. Der einzige Unterschied besteht darin, ob Sie mit allen bereitgestellten Änderungen beginnen oder mit allen nicht bereitgestellten Änderungen.
Gehen Sie jetzt hinein und bearbeiten Sie den Code. Sie können Änderungen entfernen, hinzugefügte Dateien löschen und alles tun, um das erste Commit der gesuchten Serie zu erstellen. Sie können es auch erstellen, ausführen und bestätigen, dass Sie über einen konsistenten Quellensatz verfügen.
Wenn Sie zufrieden sind, stellen Sie die Dateien nach Bedarf bereit (ich verwende sie gerne
git gui
dafür) und übernehmen Sie die Änderungen über die Benutzeroberfläche oder die BefehlszeileDas ist das erste Commit. Jetzt möchten Sie Ihre Arbeitskopie in dem Zustand wiederherstellen, den sie nach dem Festschreiben hatte, das Sie aufteilen, damit Sie mehr Änderungen für Ihr nächstes Festschreiben vornehmen können. Verwenden Sie, um den sha1 des Commits zu finden, den Sie bearbeiten
git status
. In den ersten Zeilen des Status sehen Sie den aktuell ausgeführten Rebase-Befehl, in dem Sie den sha1 Ihres ursprünglichen Commits finden:In diesem Fall hat das Commit, das ich bearbeite, sha1
65dfb6a
. Wenn ich das weiß, kann ich den Inhalt dieses Commits über mein Arbeitsverzeichnis überprüfen, wobei die Formgit checkout
sowohl ein Commit als auch einen Dateispeicherort annimmt. Hier verwende ich.
als Dateispeicherort, um die gesamte Arbeitskopie zu ersetzen:Verpassen Sie nicht den Punkt am Ende!
Dadurch werden die Dateien so überprüft und bereitgestellt, wie sie nach dem von Ihnen bearbeiteten Commit waren, jedoch relativ zum vorherigen Commit, sodass alle bereits festgeschriebenen Änderungen nicht Teil des Commits sind.
Sie können entweder jetzt fortfahren und es unverändert festschreiben, um die Aufteilung zu beenden, oder es erneut ausführen und einige Teile des Festschreibens löschen, bevor Sie ein weiteres vorläufiges Festschreiben durchführen.
Wenn Sie die ursprüngliche Festschreibungsnachricht für eine oder mehrere Festschreibungen wiederverwenden möchten, können Sie sie direkt aus den Arbeitsdateien der Rebase verwenden:
Sobald Sie alle Änderungen vorgenommen haben,
wird den Rebase-Vorgang fortsetzen und abschließen.
quelle
git checkout *Sha I'm Editing* .
heißt es immerUpdated 0 paths from *Some Sha That's Not In Git Log*
und gibt keine Änderungen.git rebase --interactive
kann verwendet werden, um ein Commit in kleinere Commits aufzuteilen. Die Git-Dokumente auf Rebase enthalten eine kurze Anleitung für den Prozess - Splitting Commits :quelle
^
um ein Escape-Zeichen für die Befehlszeile handelt: Es sollte verdoppelt werden. Zum Beispiel Ausgabegit reset HEAD^^
stattgit reset HEAD^
.^
zweimaliges Zurücksetzen werden zwei Commits über dem aktuellen HEAD zurückgesetzt."HEAD^"
in cmd.exe oder PowerShell,HEAD^^
in cmd.exe,HEAD`^
in PowerShell. Es ist hilfreich zu erfahren, wie Shells - und Ihre spezielle Shell - funktionieren (dh wie ein Befehl in einzelne Teile umgewandelt wird, die an das Programm übergeben werden), damit Sie Befehle online an die richtigen Zeichen für Ihre bestimmte Shell anpassen können. (Nicht spezifisch für Windows.)Mit dem neuesten TortoiseGit unter Windows können Sie dies jetzt ganz einfach tun.
Öffnen Sie den Rebase-Dialog, konfigurieren Sie ihn und führen Sie die folgenden Schritte aus.
Edit
" (zwischen Auswählen , Squash, Löschen ...).Start
", um die Neubasierung zu starten.Edit/Split
aktivieren Sie die Schaltfläche " " und klicken SieAmend
direkt auf " ". Der Commit-Dialog wird geöffnet.commit
".Sehr hilfreich, danke TortoiseGit!
quelle
Sie können eine interaktive Rebase durchführen
git rebase -i
. Manpage hat genau das, was Sie wollen:http://git-scm.com/docs/git-rebase#_splitting_commits
quelle
Bitte beachten Sie, dass es auch gibt
git reset --soft HEAD^
. Es ähneltgit reset
(standardmäßig--mixed
), behält jedoch den Indexinhalt bei. Wenn Sie also Dateien hinzugefügt / entfernt haben, haben Sie diese bereits im Index.Es stellt sich heraus, dass es bei riesigen Commits sehr nützlich ist.
quelle
Hier erfahren Sie , wie Sie ein Commit in IntelliJ IDEA , PyCharm , PhpStorm usw. Aufteilen
Wählen Sie im Protokollfenster der Versionskontrolle das Commit aus, das Sie teilen möchten, klicken Sie mit der rechten Maustaste und wählen Sie das aus
Interactively Rebase from Here
Markieren Sie diejenige, als die Sie teilen möchten,
edit
und klicken Sie aufStart Rebasing
Sie sollten sehen, dass ein gelbes Tag platziert ist, was bedeutet, dass der HEAD auf dieses Commit eingestellt ist. Klicken Sie mit der rechten Maustaste auf dieses Commit und wählen Sie
Undo Commit
Jetzt sind diese Commits wieder im Staging-Bereich. Sie können sie dann separat festschreiben. Nachdem alle Änderungen festgeschrieben wurden, wird das alte Festschreiben inaktiv.
quelle
Ohne eine interaktive Rebase ist es am einfachsten, (wahrscheinlich) einen neuen Zweig zu erstellen, der mit dem Commit beginnt, bevor der, den Sie teilen möchten, das Commit auswählt, zurücksetzt, speichert, die Datei verschiebt, den Stash erneut anwendet und Übernehmen Sie die Änderungen, und führen Sie sie dann entweder mit dem früheren Zweig zusammen oder wählen Sie die folgenden Festschreibungen aus. (Wechseln Sie dann den früheren Filialnamen in den aktuellen Kopf.) (Es ist wahrscheinlich besser, den Ratschlägen von MBOs zu folgen und eine interaktive Rebase durchzuführen.)
quelle
rebase -i
Vorschläge. Ich denke, dass dies aufgrund fehlender Formatierung nicht viel Beachtung fand. Vielleicht könnten Sie es überprüfen, jetzt, wo Sie 126.000 Punkte haben und wahrscheinlich wissen, wie man SO. ;)Ich denke, das ist der beste Weg, den ich benutze
git rebase -i
. Ich habe ein Video erstellt, um die Schritte zum Aufteilen eines Commits zu zeigen: https://www.youtube.com/watch?v=3EzOz7e1ADIquelle
Wenn Sie dies haben:
Wo Sie in Commit B Inhalte festgeschrieben haben:
Aber Sie möchten B in C - D aufteilen und dieses Ergebnis erhalten:
Sie können den Inhalt beispielsweise so aufteilen (Inhalte aus verschiedenen Verzeichnissen in verschiedenen Commits) ...
Setzen Sie den Zweig zurück auf das Commit vor dem zu teilenden:
Erstes Commit erstellen (C):
Erstes zweites Commit erstellen (D):
quelle
Es ist mehr als 8 Jahre her, aber vielleicht findet es trotzdem jemand hilfreich. Ich konnte den Trick ohne machen
rebase -i
. Die Idee ist, Git in den Zustand zu führen, in dem es vor Ihnen wargit commit
:Danach sehen Sie dies glänzend
Unstaged changes after reset:
und Ihr Repo befindet sich in einem Zustand, in dem Sie alle diese Dateien festschreiben möchten. Von nun an können Sie es einfach wieder festschreiben, wie Sie es normalerweise tun. Ich hoffe es hilft.quelle
Eine kurze Referenz der notwendigen Befehle, da ich im Grunde weiß, was zu tun ist, aber immer die richtige Syntax vergesse:
Dank an Emmanuel Bernards Blogbeitrag .
quelle