Fortgeschrittene Git-Verlaufsbearbeitung: Commits ändern und interaktives Rebase
Verwenden Sie git commit --amend und interaktives Rebase, um den lokalen Verlauf zu bereinigen, ohne gemeinsame Branches zu stören.
Fortgeschrittene Git-Verlaufsbearbeitung: Commits ändern und interaktives Rebase
Fortgeschrittene Git-Verlaufsbearbeitung hilft Ihnen, Commits zu bereinigen, bevor sie Teil des gemeinsamen Verlaufs werden. Wenn Sie das Ändern von Commits und interaktives Rebase verstehen, können Sie kleine Fehler beheben, verrauschte Commits zusammenfassen und eine klarere Geschichte für die Code-Überprüfung präsentieren.
Die wichtigste Regel ist einfach: Das Bearbeiten des lokalen Verlaufs ist normal, aber das Umschreiben des gemeinsamen Verlaufs erfordert Vorsicht. Die Befehle sind leistungsstark, weil sie Commit-IDs ändern, nicht nur Commit-Nachrichten.
Was die Git-Verlaufsbearbeitung tatsächlich ändert
Jeder Git-Commit hat eine ID, die auf seinem Inhalt, Metadaten, Eltern-Commit, Autor, Datum und Nachricht basiert. Wenn Sie einen Commit ändern oder während eines Rebase umschreiben, erstellt Git einen neuen Commit mit einer neuen ID.
Das ist in Ordnung, wenn der Commit nur auf Ihrem Rechner existiert. Es ist riskant, wenn andere Personen den alten Commit bereits abgerufen haben. Ihre Branches zeigen möglicherweise noch auf den alten Verlauf, während Ihrer auf den umgeschriebenen Verlauf zeigt.
Verwenden Sie die Verlaufsbearbeitung für:
- Beheben eines Tippfehlers in der neuesten Commit-Nachricht.
- Hinzufügen einer vergessenen Datei zu Ihrem letzten lokalen Commit.
- Zusammenfassen mehrerer Work-in-Progress-Commits vor dem Öffnen eines Pull-Requests.
- Neuordnen lokaler Commits, damit zusammenhängende Änderungen leichter zu überprüfen sind.
- Aufteilen eines großen lokalen Commits in kleinere logische Commits.
Vermeiden Sie die Verlaufsbearbeitung auf:
- Hauptbranches.
- Release-Branches.
- Gemeinsamen Feature-Branches, die von mehreren Personen verwendet werden.
- Jeglichen Branches mit Deployment-Tags oder audit-sensitiven Commits.
Bevor Sie beginnen, überprüfen Sie, auf welchem Branch Sie sich befinden und was bereits gepusht wurde:
git status
git branch --show-current
git log --oneline --decorate -5
Wenn Sie unsicher sind, ob das Umschreiben sicher ist, erstellen Sie einen Backup-Branch:
git branch backup-vor-rebase
Dieser Branch gibt Ihnen einen bekannten Wiederherstellungspunkt, falls das Rebase schiefgeht.
Ändern des letzten Commits
git commit --amend ersetzt den letzten Commit durch einen neuen. Es ist der schnellste Weg, den letzten Commit zu korrigieren, bevor jemand anderes darauf angewiesen ist.
Um nur die Commit-Nachricht zu bearbeiten:
git commit --amend
Git öffnet Ihren Editor mit der aktuellen Nachricht. Speichern Sie die korrigierte Nachricht, und Git erstellt einen Ersatz-Commit.
Um eine vergessene Datei zum letzten Commit hinzuzufügen:
git add pfad/zur/datei
git commit --amend --no-edit
Das Flag --no-edit behält die vorhandene Nachricht bei. Dies ist nützlich, wenn die Commit-Nachricht bereits richtig ist und Sie nur vergessen haben, eine Änderung zu stagen.
Hier ist ein häufiges Szenario. Sie committen ein Dockerfile-Update und stellen dann fest, dass Sie die zugehörige .dockerignore-Änderung vergessen haben:
git add Dockerfile
git commit -m "Docker-Build-Caching verbessern"
git add .dockerignore
git commit --amend --no-edit
Jetzt hat der Branch einen sauberen Commit anstelle eines zweiten Commits mit dem Text "Datei vergessen." Das erleichtert die Überprüfung.
Wenn der ursprüngliche Commit bereits gepusht wurde, hat der Remote-Branch immer noch die alte Commit-ID. Das Pushen des geänderten Commits erfordert eine Force-ähnliche Aktualisierung:
git push --force-with-lease
Bevorzugen Sie --force-with-lease gegenüber --force. Es verweigert das Überschreiben des Remote-Branches, wenn jemand anderes seit Ihrem letzten Fetch neue Arbeit gepusht hat.
Bereinigen mehrerer Commits mit interaktivem Rebase
Interaktives Rebase ermöglicht es Ihnen, mehrere Commits auf einmal zu bearbeiten. Sie wählen einen Bereich aus, und Git öffnet eine Todo-Liste, in der Sie Commits auswählen, umschreiben, squashen, fixupen, neu ordnen oder anhalten können.
Um die letzten fünf Commits zu bearbeiten:
git rebase -i HEAD~5
Sie sehen eine Liste wie diese:
pick a1b2c3d Deployment-Skript hinzufügen
pick b2c3d4e Tippfehler korrigieren
pick c3d4e5f Health Check hinzufügen
pick d4e5f6a Dokumentation aktualisieren
pick e5f6a7b Timeout anpassen
Ändern Sie den Befehl am Anfang jeder Zeile, um zu steuern, was passiert. Häufige Optionen sind:
pick: den Commit unverändert lassen.reword: die Änderungen behalten, aber die Nachricht bearbeiten.squash: diesen Commit mit dem vorherigen zusammenführen und die kombinierte Nachricht bearbeiten.fixup: diesen Commit mit dem vorherigen zusammenführen und die Nachricht dieses Commits verwerfen.edit: bei diesem Commit anhalten, damit Sie seinen Inhalt ändern können.drop: den Commit entfernen.
Wenn beispielsweise "Tippfehler korrigieren" zu "Deployment-Skript hinzufügen" gehört, ändern Sie die zweite Zeile:
pick a1b2c3d Deployment-Skript hinzufügen
fixup b2c3d4e Tippfehler korrigieren
pick c3d4e5f Health Check hinzufügen
pick d4e5f6a Dokumentation aktualisieren
pick e5f6a7b Timeout anpassen
Speichern und schließen Sie den Editor. Git spielt die Commits erneut ab und kombiniert die Tippfehlerkorrektur mit dem früheren Commit.
Interaktives Rebase ist auch hilfreich, um Commit-Nachrichten vor einem Pull-Request zu verbessern. Wenn drei Commits alle "update" sagen, verwenden Sie reword und machen Sie daraus Nachrichten, die die tatsächliche Änderung erklären.
Wenn ein Konflikt auftritt, lösen Sie ihn wie einen normalen Merge-Konflikt:
git status
git add aufgelöste-datei
git rebase --continue
Wenn Sie entscheiden, dass sich das Rebase nicht lohnt:
git rebase --abort
Das setzt Ihren Branch auf den Zustand vor dem Rebase zurück.
Aufteilen eines Commits während des Rebase
Manchmal enthält ein Commit zwei nicht zusammenhängende Änderungen. Sie könnten zum Beispiel einen Commit haben, der ein Kubernetes-Manifest aktualisiert und auch einen README-Abschnitt korrigiert. Diese Änderungen sollten wahrscheinlich getrennt sein.
Starten Sie ein interaktives Rebase:
git rebase -i HEAD~3
Ändern Sie pick zu edit für den Commit, den Sie aufteilen möchten. Wenn Git bei diesem Commit anhält, setzen Sie ihn zurück, während die Änderungen in Ihrem Arbeitsverzeichnis bleiben:
git reset HEAD^
Stagen und committen Sie nun das erste logische Stück:
git add k8s/deployment.yaml
git commit -m "Deployment-Health-Check aktualisieren"
Dann stagen und committen Sie das zweite Stück:
git add README.md
git commit -m "Health-Check-Verhalten dokumentieren"
Setzen Sie das Rebase fort:
git rebase --continue
Dies verwandelt einen breiten Commit in zwei fokussierte Commits. Prüfer können jede Änderung verstehen, ohne gedanklich nicht zusammenhängende Arbeit trennen zu müssen.
Wann Sie vor dem Umschreiben Hilfe holen sollten
Bitten Sie um Hilfe, bevor Sie einen Branch umschreiben, den andere Personen verwenden. Ein Teamleiter, Release-Ingenieur oder Repository-Administrator kann Ihnen sagen, ob der Branch sicher umgeschrieben werden kann und wie das Team mit Force-Pushes umgeht.
Holen Sie sich sofort Hilfe, wenn ein Rebase Commits betrifft, die bereits deployed, getaggt oder in Incident-Berichten referenziert sind. In diesen Fällen ist es oft wichtiger, den Verlauf zu bewahren, als ihn ordentlich aussehen zu lassen.
Für routinemäßige Feature-Branches ist die Verlaufsbearbeitung ein normaler Bereinigungsschritt. Verwenden Sie git commit --amend für den letzten Commit, interaktives Rebase für eine kleine lokale Serie und --force-with-lease, wenn Sie einen Remote-Branch aktualisieren müssen, der Ihnen gehört.