Git: Wie ändert man eine Commit-Nachricht?
Die letzte Commit-Nachricht zu korrigieren ist ein Befehl. Eine ältere zu korrigieren schreibt jeden Commit danach neu — was in Ordnung ist, solange nichts gepusht wurde, und ein Problem in dem Moment, in dem es das wurde.
Der jüngste Commit
user@pc:~$ git commit --amend -m "add c, properly"
before : 7c7ccf0 add c 7b6de0a add b ec8533e frist commit
after : 697735c add c, properly 7b6de0a add b ec8533e frist commit
Beachte den Hash: Aus 7c7ccf0 wurde 697735c.
--amend
bearbeitet nichts — ein Commit ist unveränderlich, git baut also einen Ersatz
und setzt den Branch darauf. Der alte bleibt verwaist zurück.
Lässt du -m weg, öffnet sich dein Editor mit der bestehenden Nachricht, was
für alles jenseits einer Zeile angenehmer ist.
Ein älterer Commit
user@pc:~$ git rebase -i HEAD~3
Das öffnet eine Liste von Commits. Ändere bei dem gewünschten pick auf
reword, speichere, und git hält an, damit du die Nachricht neu schreiben
kannst.
Zwei Details, die in den Antworten oft fehlen.
Die Zahl schließt den Ziel-Commit mit ein. HEAD~3 heißt “spiel die letzten
drei neu ein”, für den drittältesten brauchst du also mindestens HEAD~3.
Für den allerersten Commit gibt es nichts, wohin man zurückzählen könnte:
user@pc:~$ git rebase -i HEAD~3 # in einem Repo mit genau drei Commits
fatal: invalid upstream 'HEAD~3'
Der Wurzel-Commit hat keinen Elternteil. Nimm stattdessen --root:
user@pc:~$ git rebase -i --root
Wie weit das Umschreiben reicht
Das ist der Teil, den man einmal messen sollte. Die Nachricht des ältesten von drei Commits geändert:
the reworded commit : ec8533e -> 3a1977b
newest commit hash : 7c7ccf0 -> d943e4e
Jeder Commit danach hat sich ebenfalls geändert. Das ist kein Nebeneffekt: Ein Commit benennt seinen Elternteil über dessen Hash, einen Commit zu ändern ändert also zwangsläufig alle Nachfahren. Eine einzige Nachricht umzuschreiben hat den gesamten Branch darüber neu gebaut.
Solange die Commits nur dir gehören, kostet das nichts. Sobald sie gepusht sind, haben alle anderen die alte Kette, und dein nächster Push wird abgelehnt, solange du ihn nicht erzwingst — und dann widersprechen sich deren Historie und deine.
Woran du erkennst, was sicher ist
user@pc:~$ git log --oneline @{upstream}..HEAD
Das listet Commits, die du hast und der Remote nicht — genau die Menge, die du gefahrlos umschreiben kannst. Ein Fehler ist dabei ebenfalls aufschlussreich:
fatal: no upstream configured for branch 'main'
Kein Upstream heißt, dass von diesem Branch nie etwas gepusht wurde, alles darauf ist also frei.
Sind die Commits doch gepusht und geteilt, bleiben ehrlicherweise zwei
Möglichkeiten: die Nachricht so lassen, oder den erzwungenen Push vorher mit
denen abstimmen, die den Branch ebenfalls haben. --force-with-lease ist dabei
die sicherere Schreibweise, weil es sich weigert, wenn sich der Remote seit
deinem letzten Fetch bewegt hat.
Wie eine Nachricht aussehen sollte
subject: Short summary under 50 chars
body : A longer explanation, wrapped, after a blank line.
git behandelt die erste Zeile als Betreff und alles nach einer Leerzeile als
Rumpf. Diese Konvention ist der Grund, warum git log --oneline überhaupt
lesbar ist — und warum dir -m "..." -m "..." beide Teile liefert, ohne dass
sich ein Editor öffnet.
Hinweis zu Netcup (Werbung)
Der deutsche Hoster Netcup bietet unter anderem günstige und zugleich leistungsstarke Webhosting Pakete, KVM-basierte Root Server und dezidierte Server an. Mit unseren Gutscheincodes kannst du noch mehr Geld sparen (6€ bei deiner ersten Bestellung, 30% Rabatt auf alle KVM-basierten Root Server, ...).