2017-07-05 3 views
0

Ich habe einige Commits, die mehrere Commits vor HEAD sind. Während des Engagements gab es ein paar Änderungen, die inszeniert wurden, die ich nicht bemerkt hatte. Durch meine git log sah ich diese unerwünschten Veränderungen. Wenn Sie google nach 'undo changes for an arbitrary commit' suchen, werden viele Ergebnisse zurückgegeben, wenn ein gesamtes Commit rückgängig gemacht und Änderungen im Index entfernt werden. Was wäre jedoch ein Weg, um diese Änderungen in diesem willkürlichen Commit zu entfernen?Wie rückgängig machen Änderungen in einem willkürlichen Commit?

+1

Sie meinen, Sie möchten einen Commit teilweise rückgängig machen? Willst du Geschichte umschreiben? – jonrsharpe

+1

Der Befehl, den Sie suchen, ist ['git rebase --interactive'] (https://git-scm.com/docs/git-rebase#git-rebase---interactive). – axiac

+0

@jonrsharpe ich habe nichts dagegen Geschichte umschreiben. Das sind alles lokale Änderungen und ich möchte keine zusätzliche Komplexität wie das Zurücksetzen. ich möchte einfach 'AB3ej' von' {change1, change2, change3} 'zu' {change1, change2} 'gehen, zum Beispiel .. –

Antwort

1

Zuerst, stellen Sie sicher, dass Ihr Arbeitsbaum sauber ist. git status hilft Ihnen, das zu finden. Es sollten keine Änderungen gemeldet werden, die auf einen Commit warten. Wenn es Änderungen gibt, können Sie sie entweder (in einer temporären Verzweigung, falls erforderlich) oder stash sie committen.

Nachdem Sie sicherstellen, dass die Arbeits Baum sauber ist, einen Zweig auf dem aktuellen erstellen verpflichten es aber nicht check out:

$ git branch backup 

Es ist nicht wirklich nötig, können Sie die reflog stattdessen verwenden, aber es ist einfacher (und sichtbarer) auf diese Weise. backup ist nur ein Name, den ich für die Branche gewählt habe, es ist nichts Besonderes; Die einzige Einschränkung ist, dass es nicht bereits existieren muss.

Vorausgesetzt, dass Sie die dritte begehen in der Vergangenheit ändern möchten, führen Sie:

$ git rebase --interactive HEAD~4 

Git im Standard-Editor öffnet eine temporäre Datei, deren Inhalt wie folgt aussieht:

pick 7f0c5e794 the commit you want to change 
pick 9f96dcae9 commit message #2 
pick 02ed04062 commit message #3 
pick beac35780 the most recent commit 

Das ist das ist Plan für die Rebase. Natürlich enthält es die Hashes und die Themen Ihrer letzten drei Commits. Sie sind die letzten vier Commits (wegen HEAD~4) in der chronologischen Reihenfolge (älter zuerst).

Bearbeiten Sie die Zeile des Commits, das Sie ändern möchten (die erste Zeile). Ändern Sie zu edit dann speichern Sie die Datei und beenden Sie den Editor.

Wenn Sie den Editor beenden, startet Git die Umbasierung. Es überprüft das Commit HEAD~3 und beendet, so dass Sie das Commit, wie Sie es im Plan verlangten, edit können.

Nehmen Sie die gewünschten Änderungen vor, führen Sie sie aus und führen Sie git commit --amend aus, um die Festschreibung zu ändern (Ihr Ziel). Der beste Weg, um die Änderungen zu tun ist, auszuführen:

$ git reset --mixed HEAD~1 

Dies bringt den Repo in dem Status es vorher war die Commit Sie ändern mögen, mit Dateien im Arbeits Baum und nichts hinzugefügt, um den Index geändert. Fügen Sie dem Index nur die Dateien hinzu, die Sie benötigen, und stellen Sie sie fest (ohne--amend). Dies ist die "bearbeitete" commit Sie wollten.

Nachdem Sie das Commit bearbeitet haben, haben Sie noch nicht festgeschriebene Änderungen im Arbeitsbaum. Sie müssen sie entweder festlegen (erstellen Sie ein neues Commit, das nicht im ursprünglichen Verlauf vorhanden war), sie speichern (und anwenden, nachdem Sie die Rebase abgeschlossen haben) oder sie komplett verwerfen (git reset --hard tut es; stellen Sie sicher, dass Sie es wirklich nicht tun brauche sie, bevor du diesen Befehl ausführst).

Nachdem Sie das Problem der unbestätigten Änderungen eine oder andere Weise zu beheben, führen:

$ git rebase --continue 

Git setzt das Fütterungsmaterial; es verarbeitet die anderen Commits, wie Sie es im Plan gesagt haben. Unser Plan erwähnt für die anderen Commits und das bedeutet, dass Git nur die Änderungen dieser Commits anwendet, die Sie nicht ändern wollen.

Wenn alles gut geht, nachdem dieser Befehl abgeschlossen ist, haben Sie eine neue Verlaufszeile, die aussieht wie Sie wollten. Wenn es nicht so aussehen wie Sie wollen Sie laufen

$ git reset --hard backup 

zurück zu gehen, wo Sie begonnen und von vorn beginnen.

Wenn die Rebase nicht erfolgreich abgeschlossen wird (es können Konflikte auftreten), können Sie sie jederzeit abbrechen, indem Sie git rebase --abort ausführen. Git wird alle Änderungen rückgängig machen, und Sie werden dort sein, wo Sie angefangen haben (auf das Commit, auf das der Zweig backup zeigt).

Oder Sie können die Konflikte lösen, commit und den Lauf git rebase --continue, bis die Rebase abgeschlossen ist.

Nachdem Sie die Rebase auf die eine oder andere Weise beendet haben und mit dem Ergebnis zufrieden sind oder die Idee des Änderns der letzten Festschreibung beendet haben, führen Sie git branch -D backup aus, um die Sicherungsverzweigung zu entfernen.


Die Commits Git sind unveränderlich. Es ist nicht möglich, ein Commit zu bearbeiten. Das "Editieren" eines Commits erzeugt ein neues Commit, das anstelle des alten verwendet wird. Natürlich hat das neue Commit einen anderen Hash als das Original.

Das alte Commit ist immer noch im Repository vorhanden und kann über seinen Hash oder eine Verzweigung aufgerufen werden. Wenn es keine Verzweigung gibt, die verwendet werden kann, um sie zu erreichen, und in reflog kein Verweis darauf vorhanden ist, wird das Festschreibobjekt bei dem nächsten Speicherbereinigungszyklus entfernt.

+0

Ich bin etwas verwirrt durch die Schritte um '$ git reset --mixed HEAD ~ 1'. An einem Punkt empfiehlst du 'git commit --amend', aber später sage commit ohne Änderung. Gibt es ein oder zwei Commits, die mit dem 'Edit Commit' dieser Rebase verbunden sind? –

+0

Wenn Git aufhört, Sie das Commit ändern zu lassen, ist der Repo-Status derselbe, der ** nachdem ** der Commit, den Sie bearbeiten möchten, generiert wurde. Sie können entweder einige Änderungen vornehmen, sie in Szene setzen und 'git commit --amend' verwenden, um das letzte Commit (das zu bearbeitende) zu modifizieren, oder Sie können ein Commit zurückgehen (mit' git reset HEAD ~ 1') und komplett generieren neues Commit, anstatt das vorhandene zu bearbeiten.Die erste Option ist gut, wenn Sie fehlende Dateien hinzufügen oder kleine Korrekturen vornehmen möchten. Der zweite funktioniert besser, um Änderungen aus dem Commit zu entfernen. – axiac

+0

ah ich sehe, so würde 'git commit --ammend' mir erlauben, Dateien hinzuzufügen, Änderungen hinzuzufügen oder die Commit - Nachricht zu ändern, aber 'git reset HEAD ~ 1' setzt den Commit - Verlauf zurück und erlaubt mir zu löschen (nicht re -add) die Dateien, die ich aus dem Verlauf entfernen möchte und dann normal committen. Da das ursprüngliche Commit unveränderlich ist, wird ein neues Commit (neuer Hash) das alte ersetzen. ist das richtig? –

Verwandte Themen