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, ...).