Frage Brechen Sie einen vorherigen Commit in mehrere Commits


Ohne einen Zweig zu erstellen und eine Menge flippiger Arbeit an einem neuen Zweig zu erledigen, ist es möglich, einen einzelnen Commit in ein paar verschiedene Commits zu zerlegen, nachdem er an das lokale Repository übergeben wurde?


831
2018-06-02 16:11


Ursprung


Antworten:


git rebase -i werde es tun.

Beginnen Sie zunächst mit einem sauberen Arbeitsverzeichnis: git status sollte keine ausstehenden Änderungen, Löschungen oder Ergänzungen anzeigen.

Um Ihr letztes Commit zu teilen, zuerst:

$ git reset HEAD~

Verpflichten Sie nun die Teile einzeln auf die übliche Art und Weise, so viele Commits wie Sie benötigen.

Wenn es weiter hinten im Baum war, dann

$ git rebase -i HEAD~3

woher 3 ist, wie viele Commits zurück es ist.

Wenn es weiter hinten im Baum war, als Sie zählen wollen, dann

$ git rebase -i 123abcd~

woher 123abcd ist das SHA1 des Commits, das du aufteilen willst.

Wenn Sie den Rebase-Bearbeitungsbildschirm sehen, suchen Sie nach dem Commit, das Sie trennen möchten. Am Anfang dieser Zeile ersetzen pick mit edit (e kurz). Speichere den Puffer und verlasse ihn. Rebase stoppt nun direkt nach dem Commit, das Sie bearbeiten möchten. Dann:

$ git reset HEAD~

Setze die Teile einzeln auf die übliche Weise zusammen und erzeuge so viele Commits, wie du brauchst

$ git rebase --continue

1279
2018-06-02 16:26



Von Git-Rebase Handbuch (Abschnitt SPLITTING COMMITS)

Im interaktiven Modus können Sie Commits mit der Aktion "Bearbeiten" markieren. Dies bedeutet jedoch nicht unbedingt, dass git rebase erwartet, dass das Ergebnis dieser Bearbeitung genau ein Commit ist. In der Tat können Sie das Commit rückgängig machen oder andere Commits hinzufügen. Dies kann verwendet werden, um ein Commit in zwei Teile aufzuteilen:

  • Starten Sie eine interaktive Rebase mit git rebase -i <commit>^, woher <commit> ist das Commit, das Sie teilen möchten. In der Tat wird jeder Commit-Bereich ausreichen, solange er diesen Commit enthält.

  • Markieren Sie das Commit, das Sie teilen möchten, mit der Aktion "Bearbeiten".

  • Wenn Sie diesen Commit bearbeiten, führen Sie ihn aus git reset HEAD^. Der Effekt ist, dass der HEAD um eins zurückgespult wird und der Index folgt. Der Arbeitsbaum bleibt jedoch gleich.

  • Fügen Sie nun die Änderungen dem Index hinzu, den Sie beim ersten Commit haben möchten. Sie können verwenden git add (möglicherweise interaktiv) oder git gui (oder beides), um das zu tun.

  • Übergeben Sie den jetzt aktuellen Index mit der aktuellen Commit-Nachricht.

  • Wiederholen Sie die letzten beiden Schritte, bis Ihr Arbeitsbaum sauber ist.

  • Setzen Sie die Rebase mit fort git rebase --continue.


244
2018-01-22 15:05



Benutzen git rebase --interactive Um diesen früheren Commit zu bearbeiten, führen Sie ihn aus git reset HEAD~, und dann git add -p fügen Sie einige hinzu, machen Sie dann einen Commit, fügen Sie weitere hinzu und führen Sie einen weiteren Commit durch, so oft Sie möchten. Wenn du fertig bist, renn git rebase --continueund du hast alle Split-Commits früher in deinem Stack.

Wichtig: Beachten Sie, dass Sie herumspielen und alle gewünschten Änderungen vornehmen können und sich keine Gedanken über den Verlust alter Änderungen machen müssen, da Sie immer laufen können git reflog um den Punkt in Ihrem Projekt zu finden, der die gewünschten Änderungen enthält (nennen wir es) a8c4ab), und dann git reset a8c4ab.

Hier ist eine Reihe von Befehlen, die zeigen, wie es funktioniert:

mkdir git-test; cd git-test; git init

Jetzt füge eine Datei hinzu A

vi A

füge diese Zeile hinzu:

one

git commit -am one

Dann füge diese Zeile zu A hinzu:

two

git commit -am two

Dann füge diese Zeile zu A hinzu:

three

git commit -am three

Jetzt sieht die Datei A wie folgt aus:

one
two
three

und unser git log sieht wie folgt aus (gut, ich benutze git log --pretty=oneline --pretty="%h %cn %cr ---- %s"

bfb8e46 Rose Perrone 4 seconds ago ---- three
2b613bc Rose Perrone 14 seconds ago ---- two
9aac58f Rose Perrone 24 seconds ago ---- one

Nehmen wir an, wir wollen das zweite Commit aufteilen, two.

git rebase --interactive HEAD~2

Dies bringt eine Nachricht, die wie folgt aussieht:

pick 2b613bc two
pick bfb8e46 three

Ändern Sie die erste pick zu einem e um diesen Commit zu bearbeiten.

git reset HEAD~

git diff zeigt uns, dass wir gerade das Commit für das zweite Commit verschoben haben:

diff --git a/A b/A
index 5626abf..814f4a4 100644
--- a/A
+++ b/A
@@ -1 +1,2 @@
 one
+two

Lassen Sie uns diese Änderung inszenieren und fügen Sie dieser Zeile in der Datei "und eine dritte" hinzu A.

git add .

Dies ist normalerweise der Punkt während einer interaktiven Rebase, in der wir laufen würden git rebase --continue, weil wir normalerweise nur zurück in unseren Stapel von Commits gehen wollen, um einen früheren Commit zu bearbeiten. Aber dieses Mal wollen wir ein neues Commit erstellen. Also werden wir rennen git commit -am 'two and a third'. Jetzt bearbeiten wir die Datei A und füge die Zeile hinzu two and two thirds.

git add . git commit -am 'two and two thirds' git rebase --continue

Wir haben einen Konflikt mit unserem Commit, threeAlso lass es uns lösen:

Wir werden uns ändern

one
<<<<<<< HEAD
two and a third
two and two thirds
=======
two
three
>>>>>>> bfb8e46... three

zu

one
two and a third
two and two thirds
three

git add .; git rebase --continue

Jetzt unser git log -p sieht aus wie das:

commit e59ca35bae8360439823d66d459238779e5b4892
Author: Rose Perrone <roseperrone@fake.com>
Date:   Sun Jul 7 13:57:00 2013 -0700

    three

diff --git a/A b/A
index 5aef867..dd8fb63 100644
--- a/A
+++ b/A
@@ -1,3 +1,4 @@
 one
 two and a third
 two and two thirds
+three

commit 4a283ba9bf83ef664541b467acdd0bb4d770ab8e
Author: Rose Perrone <roseperrone@fake.com>
Date:   Sun Jul 7 14:07:07 2013 -0700

    two and two thirds

diff --git a/A b/A
index 575010a..5aef867 100644
--- a/A
+++ b/A
@@ -1,2 +1,3 @@
 one
 two and a third
+two and two thirds

commit 704d323ca1bc7c45ed8b1714d924adcdc83dfa44
Author: Rose Perrone <roseperrone@fake.com>
Date:   Sun Jul 7 14:06:40 2013 -0700

    two and a third

diff --git a/A b/A
index 5626abf..575010a 100644
--- a/A
+++ b/A
@@ -1 +1,2 @@
 one
+two and a third

commit 9aac58f3893488ec643fecab3c85f5a2f481586f
Author: Rose Perrone <roseperrone@fake.com>
Date:   Sun Jul 7 13:56:40 2013 -0700

    one

diff --git a/A b/A
new file mode 100644
index 0000000..5626abf
--- /dev/null
+++ b/A
@@ -0,0 +1 @@
+one

34
2017-07-07 21:10



Frühere Antworten haben die Verwendung von git rebase -i Bearbeiten Sie das Commit, das Sie teilen möchten, und übergeben Sie es in Teilen.

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.

Haben Sie zu dem Commit, das Sie teilen möchten, verwenden rebase -i und markiert es für edit, Sie haben zwei Möglichkeiten.

  1. Nach dem Gebrauch git reset HEAD~, gehen Sie mit den Patches einzeln durch git add -p um bei jedem Commit die gewünschten auszuwählen

  2. Bearbeiten Sie die Arbeitskopie, um die Änderungen zu entfernen, die Sie nicht möchten. begehen diesen Zwischenzustand; und dann ziehe das volle Commit für die nächste Runde zurück.

Option 2 ist nützlich, wenn Sie ein großes Commit aufteilen, da Sie überprüfen können, ob die vorläufigen Versionen als Teil der Zusammenführung ordnungsgemäß erstellt und ausgeführt werden. Dies läuft wie folgt ab.

Nach dem Gebrauch rebase -i und editden Commit verwenden

git reset --soft HEAD~

um die Festschreibung rückgängig zu machen, aber die festgeschriebenen Dateien im Index belassen. Sie können auch einen gemischten Reset durchführen, indem Sie --soft auslassen, je nachdem, wie nahe das Endergebnis Ihrer ursprünglichen Festschreibung ist. Der einzige Unterschied besteht darin, ob Sie mit allen vorgenommenen Änderungen beginnen oder mit ihnen alle nicht verschoben sind.

Gehe jetzt rein und bearbeite den Code. Sie können Änderungen entfernen, hinzugefügte Dateien löschen und alles tun, was Sie wollen, um das erste Commit der gesuchten Serie zu erstellen. Sie können es auch erstellen, ausführen und bestätigen, dass Sie über eine konsistente Quelle verfügen.

Wenn Sie zufrieden sind, können Sie die Dateien nach Bedarf staged / unstagieren (verwende ich gerne) git gui dafür) und die Änderungen über die Benutzeroberfläche oder die Befehlszeile festschreiben

git commit

Das ist der erste Einsatz, der gemacht wurde. Jetzt möchten Sie Ihre Arbeitskopie in den Zustand zurückversetzen, den sie nach dem Festschreiben hatten, das Sie teilen, damit Sie mehr von den Änderungen für Ihr nächstes Festschreiben übernehmen können. Um das sha1 des Commits zu finden, das Sie bearbeiten, verwenden Sie git status. In den ersten Zeilen des Status sehen Sie den Rebase-Befehl, der gerade ausgeführt wird und in dem Sie das sha1 Ihres ursprünglichen Commits finden können:

$ git status
interactive rebase in progress; onto be83b41
Last commands done (3 commands done):
   pick 4847406 US135756: add debugging to the file download code
   e 65dfb6a US135756: write data and download from remote
  (see more in file .git/rebase-merge/done)
...

In diesem Fall hat das Commit, das ich bearbeite, sha1 65dfb6a. Wenn ich das weiß, kann ich den Inhalt dieses Commits über mein Arbeitsverzeichnis mit dem Formular von git checkout Dies erfordert sowohl einen Commit- als auch einen Dateispeicherort. Hier benutze ich . als Speicherort für die gesamte Arbeitskopie:

git checkout 65dfb6a .

Verpasse nicht den Punkt am Ende!

Dadurch werden die Dateien wie nach der von Ihnen bearbeiteten Festschreibung ausgecheckt und auf die Bühne gebracht, aber relativ zu der vorherigen Festschreibung, die Sie vorgenommen haben. Daher sind Änderungen, die Sie bereits vorgenommen haben, nicht Teil der Festschreibung.

Sie können entweder jetzt fortfahren und es sozusagen übernehmen, um die Aufteilung zu beenden, oder Sie können erneut umhergehen, indem Sie einige Teile des Commits löschen, bevor Sie einen weiteren vorläufigen Commit durchführen.

Wenn Sie die ursprüngliche Commit-Nachricht für ein oder mehrere Commits wiederverwenden möchten, können Sie sie direkt aus den Arbeitsdateien der Rebase verwenden:

git commit --file .git/rebase-merge/message

Sobald Sie alle Änderungen vorgenommen haben,

git rebase --continue

wird weitermachen und den Rebase-Vorgang abschließen.


19
2018-03-31 10:23



git rebase --interactive kann verwendet werden, um ein Commit in kleinere Commits aufzuteilen. Das Git Docs auf Rebase haben eine kurze Anleitung des Prozesses - Splitting Commits:

Im interaktiven Modus können Sie Commits mit der Aktion "Bearbeiten" markieren. Dies bedeutet jedoch nicht unbedingt, dass git rebase erwartet, dass das Ergebnis dieser Änderung genau ein Commit ist. In der Tat können Sie das Commit rückgängig machen oder andere Commits hinzufügen. Dies kann verwendet werden, um ein Commit in zwei Teile aufzuteilen:

  • Starten Sie eine interaktive Rebase mit git rebase -i <commit>^, woher <commit> ist das Commit, das Sie teilen möchten. In der Tat wird jeder Commit-Bereich ausreichen, solange er diesen Commit enthält.

  • Markieren Sie das Commit, das Sie teilen möchten, mit der Aktion "Bearbeiten".

  • Wenn Sie diesen Commit bearbeiten, führen Sie ihn aus git reset HEAD^. Der Effekt ist, dass der HEAD um eins zurückgespult wird und der Index folgt. Der Arbeitsbaum bleibt jedoch gleich.

  • Fügen Sie nun die Änderungen dem Index hinzu, den Sie beim ersten Commit haben möchten. Sie können verwenden git add (möglicherweise interaktiv) oder git gui (oder beides), um das zu tun.

  • Übergeben Sie den jetzt aktuellen Index mit der aktuellen Commit-Nachricht.

  • Wiederholen Sie die letzten beiden Schritte, bis Ihr Arbeitsbaum sauber ist.

  • Setzen Sie die Rebase mit fort git rebase --continue.

Wenn Sie nicht absolut sicher sind, dass die Zwischenrevisionen konsistent sind (sie kompilieren, die Testsuite bestehen usw.), sollten Sie sie verwenden git stash um die noch nicht festgeschriebenen Änderungen nach jedem Commit zu speichern, zu testen und zu ändern, falls Fixes notwendig sind.


17
2017-07-14 22:25



Sie können eine interaktive Rebase erstellen git rebase -i. Die Manpage hat genau das, was du willst:

http://git-scm.com/docs/git-rebase#_splitting_commits


10
2018-06-02 16:15



Bitte beachten Sie, dass es auch gibt git reset --soft HEAD^. Es ist ähnlich wie git reset (standardmäßig auf --mixed) aber es behält den Indexinhalt bei. Wenn Sie also Dateien hinzugefügt / entfernt haben, haben Sie diese bereits im Index.

Es erweist sich als sehr nützlich im Falle von riesigen Commits.


7
2017-11-27 15:23



Jetzt in der neuesten TortoiseGit unter Windows können Sie es sehr einfach tun.

Öffne den Rebasedialog, Konfigurieren Sie esund mache die folgenden Schritte.

  • Klicken Sie mit der rechten Maustaste auf das Commit, das Sie teilen möchten, und wählen Sie "Edit"(unter Pick, Squash, löschen ...).
  • Klicken "Start"um zu beginnen, sich umzubasieren.
  • Sobald es zu dem Festschreiben kommt, um zu teilen, überprüfen Sie die "Edit/Split"Knopf und klicke auf "Amend"direkt. Der Bestätigungsdialog wird geöffnet.
    Edit/Split commit
  • Heben Sie die Auswahl der Dateien auf, die Sie einem separaten Commit hinzufügen möchten.
  • Bearbeiten Sie die Commit-Nachricht und klicken Sie dann auf "commit".
  • Bis Dateien zu committen sind, wird der Commit-Dialog immer wieder geöffnet. Wenn keine Datei mehr zu committen ist, werden Sie immer noch gefragt, ob Sie eine weitere Commit hinzufügen möchten.

Sehr hilfreich, danke TortoiseGit!


7
2018-04-22 10:32



Ich denke, dass ich den besten Weg benutze git rebase -i. Ich habe ein Video erstellt, um die Schritte zum Teilen eines Commits zu zeigen: https://www.youtube.com/watch?v=3EzOz7e1ADI


1
2017-07-25 11:47