Wie teilt man den letzten Commit in Git in zwei Teile auf?

Lesezeit: 8 Minuten

Benutzeravatar von Jakub Arnold
Jakob Arnold

Ich habe zwei Zweige, master und forumund ich habe gerade einige Änderungen vorgenommen forum in die ich gerne reinpicke master. Aber leider enthält der Commit, den ich mir aussuchen möchte, auch einige Modifikationen, die ich nicht möchte.

Die Lösung wäre wahrscheinlich, den falschen Commit irgendwie zu löschen und ihn durch zwei separate Commits zu ersetzen, einen mit Änderungen, die ich übernehmen möchte masterdie andere mit den restlichen Änderungen.

Ich habe es versucht

git reset --hard HEAD^

wodurch alle Änderungen gelöscht wurden, also musste ich mit zurückgehen

git reset ORIG_HEAD

Also meine Frage ist, wie geht das am besten Teilt das letzte Commit in zwei separate Commits?

Benutzeravatar von hcs42
hcs42

Sie sollten den Index verwenden. Nach einem gemischten Reset (“git zurücksetzen HEAD^”), füge den ersten Satz von Änderungen in den Index ein und übertrage sie dann. Übertrage dann den Rest.

Sie können “git hinzufügen“, um alle in einer Datei vorgenommenen Änderungen in den Index aufzunehmen. Wenn Sie nicht jede in einer Datei vorgenommene Änderung bereitstellen möchten, sondern nur einige davon, können Sie “git add -p” verwenden.

Sehen wir uns ein Beispiel an. Nehmen wir an, ich hätte eine Datei namens myfile, die den folgenden Text enthält:

something
something else
something again

Ich habe es in meinem letzten Commit so geändert, dass es jetzt so aussieht:

1
something
something else
something again
2

Jetzt entscheide ich, dass ich es in zwei Teile aufteilen möchte, und ich möchte, dass die Einfügung der ersten Zeile im ersten Commit erfolgt und die Einfügung der letzten Zeile im zweiten Commit.

Zuerst gehe ich zurück zu HEADs übergeordnetem Element, aber ich möchte die Änderungen im Dateisystem behalten, also verwende ich “git reset” ohne Argument (was einen sogenannten “gemischten” Reset durchführt):

$ git reset HEAD^
myfile: locally modified
$ cat myfile
1
something
something else
something again
2

Jetzt verwende ich “git add -p”, um die Änderungen, die ich festschreiben möchte, dem Index hinzuzufügen (= ich stelle sie bereit). “git add -p” ist ein interaktives Tool, das Sie fragt, welche Änderungen an der Datei dem Index hinzugefügt werden sollen.

$ git add -p myfile
diff --git a/myfile b/myfile
index 93db4cb..2f113ce 100644
--- a/myfile
+++ b/myfile
@@ -1,3 +1,5 @@
+1
 something
 something else
 something again
+2
Stage this hunk [y,n,a,d,/,s,e,?]? s    # split this section into two!
Split into 2 hunks.
@@ -1,3 +1,4 @@
+1
 something
 something else
 something again
Stage this hunk [y,n,a,d,/,j,J,g,e,?]? y  # yes, I want to stage this
@@ -1,3 +2,4 @@
 something
 something else
 something again
+2
Stage this hunk [y,n,a,d,/,K,g,e,?]? n   # no, I don't want to stage this

Dann übertrage ich diese erste Änderung:

$ git commit -m "Added first line"
[master cef3d4e] Added first line
 1 files changed, 1 insertions(+), 0 deletions(-)

Jetzt kann ich alle anderen Änderungen übernehmen (nämlich die Zahl “2” in der letzten Zeile):

$ git commit -am "Added last line"
[master 5e284e6] Added last line
 1 files changed, 1 insertions(+), 0 deletions(-)

Lassen Sie uns das Protokoll überprüfen, um zu sehen, welche Commits wir haben:

$ git log -p -n2 | cat
Commit 5e284e652f5e05a47ad8883d9f59ed9817be59d8
Author: ...
Date: ...

    Added last line

Diff --git a/myfile b/myfile
Index f9e1a67..2f113ce 100644
--- a/myfile
+++ b/myfile
@@ -2,3 +2,4 @@
 something
 something else
 something again
+2

Commit cef3d4e0298dd5d279a911440bb72d39410e7898
Author: ...
Date: ...

    Added first line

Diff --git a/myfile b/myfile
Index 93db4cb..f9e1a67 100644
--- a/myfile
+++ b/myfile
@@ -1,3 +1,4 @@
+1
 something
 something else
 something again

  • Ich habe mich in den letzten anderthalb Wochen langsam an Git von Mercurial gewöhnt, und es gibt einen praktischen Shortcut-Befehl git reset [--patch|-p] <commit> die Sie verwenden können, um sich die Mühe zu ersparen git add -p nach dem Zurücksetzen. Habe ich recht? Verwenden von Git 1.7.9.5.

    – trojjer

    5. März 2014 um 15:23 Uhr

  • Hier ist ein wenig mehr über diese Technik, einschließlich Rebasing, wenn es sich um einen älteren Commit handelt oder Sie N Commits in M ​​Commits ändern müssen: emmanuelbernard.com/blog/2014/04/14/… .

    – Chris Westin

    25. Februar 2015 um 21:48 Uhr

Benutzeravatar von spazm
spazm

Ziele:

  • Ich möchte einen vergangenen Commit aufteilen $splitme in zwei.
  • ich will Behalten Sie die Commit-Nachricht bei.

Planen:

  1. Rebasen Sie Interactive auf den übergeordneten Commit von $splitmeMarkierung $splitme als edit.
  2. Unstage die Dateien, die nicht Teil des ersten Commit sein sollen.
  3. Ändern Sie das aktuelle Commit, behalten Sie die Commit-Nachricht bei und ändern Sie sie bei Bedarf.
  4. Stellen Sie die Dateien zurück, die beim ersten Commit ausgelassen wurden.
  5. Commit, mit einer neuen Nachricht.
  6. Rebase fortsetzen.

Die Rebase-Schritte (1 und 7) können übersprungen werden, wenn die $splitme ist das neueste Commit.

git rebase -i $splitme^  # mark $splitme as edit
git reset HEAD^ -- $files
git commit --amend
git add $files
git commit
git rebase --continue

Wenn ich die Dateien im ersten Commit mit den Dateien im zweiten Commit austauschen wollte, würde ich dann wieder interaktiv rebasen und ihre Commit-Zeile austauschen.

  • git reset HEAD^ war das fehlende Puzzleteil. Funktioniert gut mit -p zu. Vielen Dank!

    – Marius Gedminas

    21. November 2013 um 12:00 Uhr

  • Es ist wichtig, die zu beachten -- $files Argument zu git reset. Mit Pfaden passiert, git reset stellt diese Dateien auf den Zustand des referenzierten Commits wieder her, ändert aber keine Commits. Wenn Sie die Pfade weglassen, “verlieren” Sie den Commit, den Sie im nächsten Schritt ändern möchten.

    – Duell-Marker

    28. Mai 2014 um 22:08 Uhr

  • Diese Methode verhindert, dass Sie Ihre erste Commit-Nachricht im Vergleich zur akzeptierten Antwort erneut kopieren und einfügen müssen.

    – Kalvin

    7. Januar 2015 um 23:02 Uhr

  • Außerdem: Wenn Sie alle Dateien zurücksetzen möchten, verwenden Sie einfach git reset HEAD^ -- .. Äußerst überraschend ist dies nicht genau das Verhalten von git reset HEAD^.

    – alles was ich mache ist gewinnen

    17. Juli 2019 um 21:21 Uhr

  • @duelinmarkers Genau, git reset HEAD^ . setzt die zurück Index zum übergeordneten Commit, aber der HEAD bleibt auf dem aktuellen Commit, wohingegen git reset HEAD^ setzt die zurück KOPF zum übergeordneten Commit. Also eine Folge git commit --amend Wille ersetzen das aktuelle Commit im ersten Fall und das übergeordnete Commit im zweiten Fall. Deshalb sollten Sie im zweiten Fall stattdessen tun git commit zu erstellen ein neues Commit (dies ist die Methode in dieser Antwort). Die Methode in dieser Antwort hat den Vorteil, dass sie Zugriff auf die geänderte Commit-Nachricht gewährt.

    – Maggyero

    14. November 2022 um 14:26 Uhr

Um den aktuellen Commit in zwei Commits zu ändern, können Sie etwa Folgendes tun.

Entweder:

git reset --soft HEAD^

Dies macht den letzten Commit rückgängig, lässt aber alles inszeniert. Sie können dann bestimmte Dateien aus der Staging-Phase entfernen:

git reset -- file.file

Optional können Sie Teile dieser Dateien erneut inszenieren:

git add -p file.file

Machen Sie einen neuen ersten Commit:

git commit

Stellen Sie die restlichen Änderungen bereit und übertragen Sie sie in einem zweiten Commit:

git commit -a

Oder:

Machen Sie alle Änderungen seit dem letzten Commit rückgängig und entfernen Sie die Bereitstellung:

git reset HEAD^

Selektiv die erste Änderungsrunde inszenieren:

git add -p

Begehen:

git commit

Übernehmen Sie die restlichen Änderungen:

git commit -a

(Wenn Sie in beiden Schritten einen Commit rückgängig gemacht haben, der eine brandneue Datei hinzugefügt hat, und diese zum zweiten Commit hinzufügen möchten, müssen Sie sie manuell als hinzufügen commit -a stellt nur Änderungen an bereits verfolgten Dateien bereit.)

Michael Krelin - Benutzeravatar des Hackers
Michael Krelin – Hacker

Laufen git guiwählen Sie das Optionsfeld “Letzten Commit ändern” und heben Sie die Bereitstellung auf (Commit > Unstage From Commit oder StrgU) Änderungen, die Sie nicht in den ersten Commit aufnehmen möchten. Ich denke, das ist der einfachste Weg, dies zu tun.

Eine andere Sache, die Sie tun könnten, ist, die Änderung herauszupicken, ohne sich zu verpflichten (git cherry-pick -n) und dann entweder manuell oder mit git gui Wählen Sie die gewünschten Änderungen aus, bevor Sie sie bestätigen.

git reset HEAD^

das –hard ist das, was Ihre Änderungen zerstört.

Benutzeravatar von dahlbyk
dahlbyk

Ich bin überrascht, dass niemand vorgeschlagen hat git cherry-pick -n forum. Dadurch werden die Änderungen vom letzten inszeniert forum begehen, aber nicht begehen – dann können Sie reset Entfernen Sie die Änderungen, die Sie nicht benötigen, und schreiben Sie fest, was Sie behalten möchten.

Die Double-Revert-Squash-Methode

  1. Führen Sie einen weiteren Commit durch, der die unerwünschten Änderungen entfernt. (Wenn es pro Datei ist, ist das wirklich einfach: git checkout HEAD~1 -- files with unwanted changes und git commit. Andernfalls können Dateien mit gemischten Änderungen teilweise bereitgestellt werden git reset file und git add -p file als Zwischenschritt.) Nennen Sie dies die zurückkehren.
  2. git revert HEAD – Machen Sie noch einen weiteren Commit, der die unerwünschten Änderungen wieder hinzufügt. Dies ist das doppelt zurück
  3. Von den 2 Commits, die Sie jetzt gemacht haben, quetschen der erste auf den zu teilenden Commit (git rebase -i HEAD~3). Dieser Commit wird nun frei von den unerwünschten Änderungen, denn diese befinden sich im zweiten Commit.

Vorteile

  • Behält die Commit-Nachricht bei
  • Funktioniert auch, wenn der Commit zum Aufteilen nicht der letzte ist. Es erfordert lediglich, dass die unerwünschten Änderungen nicht mit späteren Commits in Konflikt geraten

1441090cookie-checkWie teilt man den letzten Commit in Git in zwei Teile auf?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy