it-swarm.com.de

So teilen Sie das letzte Commit in Git in zwei Teile auf

Ich habe zwei Arbeitszweige, master und forum und ich habe gerade einige Änderungen in forum branch vorgenommen, die ich gerne in master auswählen möchte. Aber leider enthält das Commit, das ich zum Kirschpicken bringen möchte, auch einige Modifikationen, die ich nicht will.

Die Lösung wäre wahrscheinlich, das falsche Commit irgendwie zu löschen und durch zwei separate Commits zu ersetzen, eines mit Änderungen, die ich im Master auswählen möchte, und andere, die nicht dorthin gehören.

Ich habe es versucht

git reset --hard HEAD^

was alle Änderungen löschte, also musste ich zurückgehen

git reset ORIG_HEAD

Meine Frage ist also: Was ist der beste Weg, um spalten das letzte Commit in zwei separate Commits zu machen?

271
Jakub Arnold

Sie sollten den Index verwenden. Fügen Sie nach einem gemischten Reset (" git reset HEAD ^") den ersten Satz der Änderungen in den Index ein, und legen Sie sie fest. Dann begehen Sie denrest.

Sie können " git add " verwenden, um alle in einer Datei vorgenommenen Änderungen in den Index zu übernehmen. Wenn Sie Nicht jede Änderung in einer Datei in Szene setzen möchten, nur einige davon, können Sie "Git add -p" verwenden.

Lassen Sie uns ein Beispiel sehen. Nehmen wir an, ich hatte 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 teilen möchte, und ich möchte, dass die Einfügung der ersten Zeile in der ersten Übergabe und die Einfügung der letzten Zeile in der zweiten Übergabe ist.

Zuerst gehe ich zurück zu HEADs Elternteil, aber ich möchte die Änderungen im Dateisystem beibehalten, Ich verwende "git reset" ohne Argument (was ein sogenanntes "mixed" Reset bewirkt):

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

Jetzt füge ich "git add -p" hinzu, um die Änderungen, die ich festschreiben möchte, in den Index einzufügen (= I Stage). "git add -p" ist ein interaktives Tool, das Sie nach den Änderungen an der Datei fragt, die geändert werden sollen, falls sie zum Index hinzugefügt werden.

$ 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 verpflichte ich mich zu dieser ersten Änderung:

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

Nun kann ich alle anderen Änderungen übernehmen (nämlich die Ziffer "2" in die letzte Zeile setzen):

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

Sehen wir uns das Protokoll an, 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
325
hcs42

Tore:

  • Ich möchte ein Commit der Vergangenheit (splitme) in zwei Teile aufteilen.
  • Ich möchte die Commit-Nachricht beibehalten .

Planen:

  1. interbasierte Basis von einer vor splitme
  2. edit splitme
  3. Setzen Sie die Dateien zurück, um sie in ein zweites Commit aufzuteilen. 
  4. Commit ändern, Nachricht pflegen, bei Bedarf ändern.
  5. Fügen Sie die Dateien wieder hinzu, die vom ersten Commit aus aufgesplittet wurden.
  6. Commit mit einer neuen Nachricht. 
  7. Fahren Sie mit der Erneuerung fort. 

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

git rebase -i splitme^
# mark splitme commit with 'e'
git reset HEAD^ -- $files
git commit --amend
git add $files
git commit -m "commit with just some files"
git rebase --continue

Wenn ich wollte, dass die Split-Dateien zuerst festgeschrieben werden, würde ich -i erneut rebase und die Reihenfolge ändern

git rebase -i splitme^
# swap order of splitme and 'just some files'
81
spazm

Um das aktuelle Commit in zwei Commits zu ändern, können Sie Folgendes tun.

Entweder:

git reset --soft HEAD^

Dies macht das letzte Commit rückgängig, lässt aber alles in Szene. Sie können dann bestimmte Dateien entpacken:

git reset -- file.file

Fassen Sie Teile dieser Dateien optional neu an:

git add -p file.file

Machen Sie ein neues erstes Commit:

git commit

Die Etappe und der Rest der Änderungen in einem zweiten Commit:

git commit -a

Oder:

Machen Sie alle Änderungen des letzten Commits rückgängig:

git reset HEAD^

Selektiv inszenieren Sie die erste Änderungsrunde:

git add -p

Verpflichten:

git commit

Übernehmen Sie die restlichen Änderungen:

git commit -a

(Wenn Sie in einem Schritt ein Commit aufgehoben haben, das eine brandneue Datei hinzugefügt hat, und dies dem zweiten Commit hinzufügen möchten, müssen Sie es manuell hinzufügen, da commit -a nur Änderungen an bereits nachverfolgten Dateien vornimmt.)

52
CB Bailey

Führen Sie git gui aus, aktivieren Sie das Optionsfeld "Amend last commit" und deaktivieren Sie die Bühne (Commit> Unstage From Commit, oder Ctrl-U) Änderungen, die Sie beim ersten Festschreiben nicht ausführen möchten. Ich denke, das ist der einfachste Weg, dies zu tun.

Sie können die Änderung auch auswählen, ohne sie zu bestätigen (git cherry-pick -n), und dann entweder manuell oder mit git gui die gewünschten Änderungen auswählen, bevor Sie sie bestätigen.

git reset HEAD^

das --hard ist das, was deine Änderungen tötet.

15
semanticart

Ich bin überrascht, dass niemand git cherry-pick -n forum vorgeschlagen hat. Dadurch werden die Änderungen gegenüber dem letzten forum-Commit bereitgestellt, jedoch nicht festgeschrieben. Sie können dann reset die Änderungen, die Sie nicht benötigen, weglassen und das festschreiben, was Sie behalten möchten.

13
dahlbyk

Die Double-Revert-Squash-Methode

  1. Nehmen Sie ein weiteres Commit vor, das die unerwünschten Änderungen entfernt. (Wenn es sich um eine Datei handelt, ist dies sehr einfach: git checkout HEAD~1 -- files with unwanted changes und git commit. Wenn dies nicht der Fall ist, können Dateien mit gemischten Änderungen git reset file und git add -p file als Zwischenschritt teilweise bereitgestellt werden.) Rufen Sie das revert auf.
  2. git revert HEAD - Nehmen Sie ein weiteres Commit vor, das die unerwünschten Änderungen wieder hinzufügt. Dies ist das double-revert
  3. Von den 2 Commits, die Sie jetzt gemacht haben, ist squash das erste auf das Commit zu teilen (git rebase -i HEAD~3). Dieses Commit wird jetzt frei von unerwünschten Änderungen, denn diese sind im zweiten Commit.

Leistungen

  • Behält die Commit-Nachricht bei
  • Funktioniert auch dann, wenn das Commit zum Aufteilen nicht das letzte ist. Es ist lediglich erforderlich, dass die unerwünschten Änderungen nicht mit späteren Commits in Konflikt stehen
2
user2394284

Da Sie Kirschen pflücken, können Sie:

  1. cherry-pick mit der hinzugefügten --no-commit-Option.
  2. reset und verwenden Sie add --patch, add --edit oder einfach add, um das zu inszenieren, was Sie behalten möchten.
  3. commit die inszenierten Änderungen .
    • Um die ursprüngliche Festschreibungsnachricht erneut zu verwenden, können Sie dem Befehl commit Optionen für --reuse-message=<old-commit-ref> oder --reedit-message=<old-commit-ref> hinzufügen.
  4. Mit reset --hard können Sie nicht gespeicherte Änderungen wegblasen.

Eine andere Möglichkeit, die ursprüngliche Festschreibungsnachricht beizubehalten oder zu bearbeiten:

  1. cherry-pick das ursprüngliche Commit als normal.
  2. Kehren Sie die nicht gewünschten Änderungen um und verwenden Sie add, um die Umkehrung durchzuführen.
    • Dieser Schritt wäre einfach, wenn Sie entfernen, was Sie hinzugefügt haben, aber ein bisschen schwierig, wenn Sie hinzufügen, was Sie entfernt haben, oder eine Änderung rückgängig machen.
  3. commit --amend, um die Umkehrung des von der Kirsche ausgewählten Commit durchzuführen .
    • Sie erhalten wieder dieselbe Commit-Nachricht, die Sie bei Bedarf beibehalten oder überarbeiten können.
1
ADTC

Dies könnte eine andere Lösung sein, die für Fälle gedacht ist, in denen ein großes Commit vorliegt und eine kleine Anzahl von Dateien in ein neues Commit verschoben werden muss. Dies funktioniert, wenn ein Satz von <path>-Dateien aus dem letzten Commit bei HEAD extrahiert und alle in ein neues Commit verschoben werden sollen. Wenn mehrere Commits erforderlich sind, können die anderen Lösungen verwendet werden.

Machen Sie zunächst Patches in den bereitgestellten und nicht bereitgestellten Bereichen, die die Änderungen enthalten würden, um den Code vor der Änderung bzw. nach der Änderung wiederherzustellen:

git reset HEAD^ <path>

$ git status
On branch <your-branch>
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   <path>

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   <path>

Um zu verstehen, was passieren wird (Pfeil und Kommentare sind nicht Teil des Befehls):

git diff --cached   -> show staged changes to revert <path> to before HEAD
git diff            -> show unstaged changes to add current <path> changes

<path>-Änderungen beim letzten Commit rückgängig machen:

git commit --amend  -> reverts changes on HEAD by amending with staged changes

Neues Commit mit <path> Änderungen erstellen:

git commit -a -m "New Commit" -> adds new commit with unstaged changes

Dies hat den Effekt, dass ein neues Commit erstellt wird, das die aus dem letzten Commit extrahierten Änderungen enthält.

0
Jose Cifuentes