Wie kann ich einen in der Historie vergrabenen Git-Commit aufteilen?

Lesezeit: 7 Minuten

Wie kann ich einen in der Historie vergrabenen Git Commit aufteilen
Ben

Ich habe meinen Verlauf aufgeräumt und möchte einige Änderungen daran vornehmen. Das Problem ist, dass ich einen Commit mit zwei unabhängigen Änderungen habe und dieser Commit von einigen anderen Änderungen in meinem lokalen (nicht gepushten) Verlauf umgeben ist.

Ich möchte diesen Commit aufteilen, bevor ich ihn veröffentliche, aber die meisten Leitfäden, die ich sehe, haben mit dem Aufteilen Ihres letzten Commit oder nicht festgeschriebenen lokalen Änderungen zu tun. Ist es machbar, dies mit einem Commit zu tun, das ein wenig in der Geschichte vergraben ist, ohne meine Commits seitdem “erneut machen” zu müssen?

  • mögliches Duplikat von Split a commit of a copy+modify in einen copy commit und einen modify commit using git

    Benutzer456814

    14. Juli 2013 um 19:20 Uhr

Wie kann ich einen in der Historie vergrabenen Git Commit aufteilen
Cascabel

Es gibt eine Anleitung zum Teilen von Commits in der Rebase-Manpage. Die schnelle Zusammenfassung lautet:

  • Führen Sie ein interaktives Rebase einschließlich des Zielcommits durch (z git rebase -i <commit-to-split>^ branch) und zum Bearbeiten markieren.

  • Wenn die Rebase diesen Commit erreicht, verwenden Sie git reset HEAD^ vor dem Festschreiben zurückzusetzen, aber halten Sie Ihren Arbeitsbaum intakt.

  • Fügen Sie Änderungen schrittweise hinzu und schreiben Sie sie fest, indem 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. Verwenden commit -c ORIG_HEAD wenn Sie die ursprüngliche Commit-Nachricht für einen bestimmten Commit wiederverwenden möchten.

  • Wenn Sie testen möchten, was Sie verwenden (gute Idee!). git stash um den Teil zu verstecken, den Sie nicht begangen haben (oder stash --keep-index bevor Sie es überhaupt begehen), testen Sie es dann git stash pop um den Rest an den Arbeitsbaum zurückzugeben. Führen Sie weiterhin Commits durch, bis Sie alle Änderungen festgeschrieben haben, dh einen sauberen Arbeitsbaum haben.

  • Laufen git rebase --continue um mit der Anwendung der Commits nach dem jetzt geteilten Commit fortzufahren.

  • … aber nichts davon, wenn Sie den Verlauf bereits seit dem Commit zum Teilen gepusht haben.

    – wilhelmtel

    29. November 2010 um 19:22 Uhr

  • @wilhelmtell: Ich habe mein übliches “potenziell gefährlich; siehe ‘Wiederherstellung von Upstream-Rebase'”-Boilerplate weggelassen, weil das OP ausdrücklich gesagt hat, dass er diesen Verlauf nicht verschoben hat.

    – Kaskabel

    29. November 2010 um 21:52 Uhr

  • und du hast es perfekt gelesen. Ich habe versucht, das “Boilerplate” zu vermeiden, als ich angab, dass es sich noch nicht um einen geteilten Verlauf handelt 🙂 In jeder Hinsicht hatte ich Erfolg mit Ihrem Vorschlag. Es ist jedoch ein großer Schmerz, dieses Zeug im Nachhinein zu tun. Ich habe hier eine Lektion gelernt, und zwar sicherzustellen, dass die Commits von Anfang an richtig eingegeben werden!

    – Ben

    30. November 2010 um 2:03 Uhr

  • Der erste Schritt könnte besser ausgedrückt werden als git rebase -i <sha1_of_the_commit_to_split>^ branch. Und git gui ist ein nettes Werkzeug für die Splitting-Aufgabe, mit dem verschiedene Teile einer Datei in verschiedene Commits eingefügt werden können.

    – Qiang Xu

    2. April 2012 um 20:23 Uhr


  • @QiangXu: Der erste ist ein vernünftiger Vorschlag. Das zweite ist genau der Grund, warum ich vorgeschlagen habe git add -pdie mehr können als git gui kann in dieser Abteilung (insbesondere Hunks bearbeiten, alles ab dem aktuellen Hunk inszenieren und nach Hunks per Regex suchen).

    – Kaskabel

    3. April 2012 um 1:30 Uhr

Hier ist, wie man es mit macht Magit.

Sagen Sie, dass commit ed417ae derjenige ist, den Sie ändern möchten; es enthält zwei unabhängige Änderungen und ist unter einem oder mehreren Commits begraben. Getroffen haben ll um das Protokoll anzuzeigen und zu ed417ae zu navigieren:

anfängliches Protokoll

Dann zuschlagen r um das Rebase-Popup zu öffnen

Rebase-Popup

und m um den Commit an Punkt zu ändern.

Beachten Sie, wie die @ gibt es jetzt auf dem Commit, das Sie aufteilen möchten – das bedeutet, dass HEAD jetzt bei diesem Commit ist:

Ändern eines Commits

Wir wollen HEAD zum Elternteil verschieben, also navigieren Sie zum Elternteil (47e18b3) und drücken Sie x (magit-reset-quicklygebunden an o wenn Sie verwenden evil-magit) und geben Sie ein, um “Ja, ich meinte, an Punkt festschreiben” zu sagen. Ihr Protokoll sollte jetzt so aussehen:

Protokoll nach dem Zurücksetzen

Jetzt zuschlagen q um zum regulären Magit-Status zu wechseln, verwenden Sie dann die reguläre Unstage u Befehl zum Unstaging dessen, was nicht in den ersten Commit geht, commit c der rest dann wie immer stage und cLassen Sie weg, was in den zweiten Commit geht, und wenn Sie fertig sind: Hit r um das Rebase-Popup zu öffnen

Rebase-Popup

und ein anderer r um fortzufahren, und du bist fertig! ll zeigt jetzt:

alles erledigt protokollieren

1646259497 928 Wie kann ich einen in der Historie vergrabenen Git Commit aufteilen
ruvim

Um ein Commit aufzuteilen <commit> und füge die hinzu neues Commit vor diesemund speichern Sie das Autordatum von <commit>— die Schritte sind folgende:

  1. Bearbeiten Sie das Commit Vor <commit>

    git rebase -i <commit>^^
    

    NB: Vielleicht wird es auch zum Bearbeiten benötigt <commit> auch.

  2. Kirschpflücker <commit> in den Index

    git cherry-pick -n <commit>
    
  3. Setzen Sie interaktiv nicht benötigte Änderungen aus dem Index zurück und setzen Sie den Arbeitsbaum zurück

    git reset -p && git checkout-index -f -a
    

    Alternativ können Sie nicht benötigte Änderungen einfach interaktiv speichern: git stash push -p -m "tmp other changes"

  4. Nehmen Sie weitere Änderungen vor (falls vorhanden) und erstellen Sie das neue Commit

    git commit -m "upd something" .
    

    Wiederholen Sie optional die Punkte 2-4, um weitere Zwischen-Commits hinzuzufügen.

  5. Setzen Sie die Umbasierung fort

    git rebase --continue
    

Es gibt eine schnellere Version, wenn Sie nur Inhalte aus nur einer Datei extrahieren möchten. Es ist schneller, weil das interaktive Rebase nicht mehr wirklich interaktiv ist (und es ist natürlich noch schneller, wenn Sie aus dem letzten Commit extrahieren möchten, dann müssen Sie überhaupt nicht rebasen).

  1. Verwenden Sie Ihren Editor und löschen Sie die Zeilen, aus denen Sie extrahieren möchten the_file. Nah dran the_file. Das ist die einzige Edition, die Sie brauchen, der Rest sind nur Git-Befehle.
  2. Führen Sie diese Löschung im Index durch:

    git  add  the_file
    
  3. Stellen Sie die gerade gelöschten Zeilen wieder in der Datei wieder her ohne den Index zu beeinflussen!

    git show HEAD:./the_file > the_file
    
  4. “SHA1” ist der Commit, aus dem Sie die Zeilen extrahieren möchten:

    git commit -m 'fixup! SHA1' 
    
  5. Erstellen Sie das zweite, brandneue Commit mit dem zu extrahierenden Inhalt, der durch Schritt 3 wiederhergestellt wurde:

    git commit -m 'second and new commit' the_file 
    
  6. Nicht bearbeiten, nicht stoppen/fortfahren – einfach alles akzeptieren:

    git rebase --autosquash -i SHA1~1
    

Natürlich noch schneller, wenn der zu extrahierende Commit der letzte Commit ist:

4. git commit -C HEAD --amend
5. git commit -m 'second and new commit' thefile
6. no rebase, nothing

Wenn du benutzt magit dann sind die Schritte 4, 5 und 6 eine einzelne Aktion: Festschreiben, sofortige Korrektur

Auch das manuelle Korrigieren der Historie per Rosinenpicken kann in manchen Fällen funktionieren.

Ich verwende lieber meine Git-GUI (statt der Kommandozeile), mein problematischer Commit war nur 3 Commits nach unten, ich habe noch keinen gepusht, und die folgenden waren auch nicht gerade sauber, also habe ich mich für eine vollständige Rekonstruktion entschieden von ihnen durch Rosinenpickerei, und es war schneller als die Verwendung der interaktiven Rebase-Bearbeitungen über die Befehlszeile, aber ähnlich im Ansatz.

So habe ich es in meiner bevorzugten Git-GUI gemacht (ich persönlich benutze SourceTree):

  1. Ein … kreieren Schild auf den aktuellen Stand, damit er nicht verloren geht.
  2. Jetzt Bewegung Ihre tatsächliche lokale Verzweigungszeiger zum chaotischen Commit.
  3. Zurücksetzen (gemischt) auf den vorherigensodass die Dateien aus dem Commit in (2) erhalten bleiben.
  4. Du kannst jetzt Teilen Sie den Commit in zwei Teile auf oder mehr, indem benötigte Dateien bereitgestellt und mit der richtigen Nachricht übergeben werden, bis keine nicht bereitgestellten Dateien mehr übrig sind.
  5. Kirschpflücker das nächste Commit in der Reihe (aus dem Verlauf, den Sie markiert haben). Sie tun dies, indem Sie mit der rechten Maustaste auf das gewünschte Commit klicken und “Cherry Pick” auswählen. Gehe zu (4), mache es, bis keine nicht erfassten Commits mehr übrig sind.
  6. Machen Sie sich keine Sorgen, wenn Sie dadurch einige Commits haben, die am besten zu einem zusammengefasst werden. Sie können sie mit einem optionalen zerquetschen interaktive Rebase im GUI. Es ist so einfach, vor dem Durcheinander mit der rechten Maustaste auf das Commit zu klicken und auf „Interactive rebase“ zu klicken und dann Commits aufeinander zu ziehen, um sie zu squashen (die Commit-Nachricht reparieren, um es einfach zu halten), oder sie wie gewünscht nach oben oder unten zu verschieben.
  7. Entfernen Sie das Etikett erstellt in (1).

Wie kann ich einen in der Historie vergrabenen Git Commit aufteilen
Gintautas Miliauskas

Wenn Sie noch nicht gepusht haben, verwenden Sie einfach git rebase. Noch besser, verwenden git rebase -i um Commits interaktiv zu verschieben. Sie können das anstößige Commit nach vorne verschieben, es dann nach Belieben aufteilen und die Patches nach hinten verschieben (falls erforderlich).

916700cookie-checkWie kann ich einen in der Historie vergrabenen Git-Commit aufteilen?

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

Privacy policy