Ein Durchlauf des Tutorials Einen Commit rückgängig machen: warum der letzte Commit kaputt ist und wie git reset --soft ihn ohne Arbeitsverlust korrigieren lässt.
Dieses Szenario beginnt in einem Portfolio-Projekt, in dem der letzte Commit subtil kaputt ist. Sie lesen die Historie, machen den Commit rückgängig, ohne Ihre Änderungen zu verlieren, und commiten ihn richtig neu. So sieht jeder Schritt aus und warum.
Die Situation
Nur einige Dateien wurden gestaged, daher ist der Commit unvollständig.
Das Projekt hat zwei Commits. Der jüngste, „Add header section", hat einen Navigations-Header zu index.html hinzugefügt. Das passende CSS für diesen Header wurde in style.css geschrieben, aber nie gestaged: Es liegt weiterhin als nicht commitete Änderung im Arbeitsbaum.
Der Commit ist also unvollständig. Die commitete Seite enthält Header-Markup, das auf nicht gespeicherte Styles verweist. Wer diesen Commit auscheckt, bekommt einen kaputten Header zu sehen.
Starten Sie mit git log --oneline und git status. Das Log zeigt den Commit „Add header section"; status zeigt style.css als modifiziert, aber nicht gestaged. Diese Diskrepanz ist das ganze Problem.
Die Korrektur Schritt für Schritt
git reset --soft bewegt HEAD einen Commit zurück und behält Ihre Änderungen gestaged.
Prüfen, was commitet wurde
git log bestätigt den letzten Commit, und git status zeigt, dass style.css immer noch im Arbeitsbaum modifiziert ist. Damit wissen Sie, dass der Commit index.html, aber nicht style.css erfasst hat.
Den Commit rückgängig machen, Änderungen behalten
git reset --soft HEAD~1
Das setzt den Branch-Zeiger um einen Commit zurück. Die index.html-Änderung, die im Commit war, kehrt in die Staging-Area zurück, bereit, erneut commitet zu werden. Nichts in Ihren Dateien wird gelöscht.
Diesmal alles stagen
git add index.html style.css
Markup und passende Styles sind nun gemeinsam gestaged, sodass der nächste Commit vollständig wird.
Die vollständige Änderung neu commiten
git commit -m "Add header section"
Die Historie hat wieder einen einzelnen Commit „Add header section", aber diesmal inklusive style.css. Die Seite ist heil.
Warum hier --soft richtig ist
git reset hat drei Modi; der Unterschied liegt nur darin, wo Ihre Änderungen landen:
--soft bewegt HEAD zurück und behält die Änderungen gestaged. Hier ideal, weil Sie sofort neu commiten wollen.
--mixed (Standard) behält die Änderungen, aber ungestaged, im Arbeitsbaum.
--hard verwirft die Änderungen vollständig.
git reset --hard HEAD~1 würde hier zusammen mit dem Commit auch die Header-Arbeit löschen. Greifen Sie zu --hard nur, wenn Sie die Änderungen wirklich loswerden wollen.
Falls Sie --hard versehentlich ausführen, ist der Commit meist noch mit git reflog rettbar, das jede Position auflistet, die HEAD eingenommen hat. Das Tutorial „Recover Lost Commits" behandelt diesen Weg.
Eine Einschränkung: geteilte Commits
Alles oben Genannte schreibt die Historie um, was bei einem nur lokal existierenden Commit völlig sicher ist. Sobald ein Commit gepusht und von anderen gepullt wurde, zwingt das Umschreiben alle in einen divergierten Branch. Auf einem geteilten Branch heben Sie die Änderung mit einem neuen Commit auf:
git revert HEAD
Jede Möglichkeit, einen Commit rückgängig zu machen
Die drei Reset-Modi unterscheiden sich nur darin, wo Ihre Änderungen landen.
Der richtige Befehl hängt davon ab, was Sie behalten wollen. Dieses Szenario nutzte --soft; hier ist der komplette Satz:
- Den letzten Commit rückgängig machen, Änderungen gestaged behalten —
git reset --soft HEAD~1
- Den letzten Commit rückgängig machen, Änderungen ungestaged behalten —
git reset HEAD~1 (der Standard, --mixed)
- Den letzten Commit rückgängig machen und seine Änderungen verwerfen —
git reset --hard HEAD~1
- Die letzten N Commits rückgängig machen, die Arbeit behalten —
git reset --soft HEAD~N
- Nachricht oder Inhalt des letzten Commits an Ort und Stelle ändern —
git commit --amend
- Einen bereits gepushten Commit rückgängig machen —
git revert <commit>
reset schreibt die Historie um und eignet sich für Commits, die nur auf Ihrem Rechner leben; revert fügt einen neuen Commit hinzu, der einen alten aufhebt, und ist die sichere Wahl auf einem Branch, den andere gepullt haben. Probieren Sie hier jede Variante aus, damit der Unterschied zwischen Behalten, Unstagen und Verwerfen Ihrer Arbeit zur zweiten Natur wird.