Wie bearbeite ich eine falsche Commit-Nachricht in Git (die ich gepusht habe)?


152

Ich möchte eine Commit-Nachricht tiefer in der Geschichte ändern und habe viele neue Commits gepusht.

Wie ändere ich die Commit-Nachricht? Ist es möglich?

Antworten:


125

Die Nachricht von Linus Torvalds kann Ihre Frage beantworten:

Ändern / bearbeiten Sie alte Commit-Nachrichten

Kurze Antwort: Sie können nicht (wenn gedrückt).


Auszug (Linus bezeichnet BitKeeper als BK):

Randnotiz, nur aus historischem Interesse: In BK könnte man.

Und wenn Sie daran gewöhnt sind (wie ich), war es wirklich sehr praktisch. Ich würde eine Patchbombe von Andrew anwenden, feststellen, dass etwas nicht stimmt, und sie einfach bearbeiten, bevor ich sie herausschiebe.

Ich hätte dasselbe mit git machen können. Es wäre einfach genug gewesen, nur die Festschreibungsnachricht nicht Teil des Namens zu machen und dennoch zu garantieren, dass der Verlauf unberührt blieb, und die Sache "Kommentare später korrigieren" zuzulassen.

Aber ich habe es nicht getan.

Ein Teil davon ist reine "interne Konsistenz". Git ist einfach ein saubereres System, da alles SHA1-geschützt ist und alle Objekte unabhängig vom Objekttyp gleich behandelt werden. Ja, es gibt vier verschiedene Arten von Objekten, und sie sind alle sehr unterschiedlich, und sie können nicht auf die gleiche Weise verwendet werden, aber gleichzeitig funktionieren sie konzeptionell alle genau , auch wenn ihre Codierung auf der Festplatte unterschiedlich sein kann das Gleiche.

Aber interne Konsistenz ist keine Entschuldigung dafür, unflexibel zu sein, und es wäre natürlich sehr flexibel, wenn wir Fehler einfach beheben könnten, nachdem sie aufgetreten sind. Das ist also kein wirklich starkes Argument.

Der wahre Grund, warum Sie mit git die Commit-Nachricht nicht ändern können, ist sehr einfach: Auf diese Weise können Sie den Nachrichten vertrauen. Wenn Sie Personen erlaubt haben, sie später zu ändern, sind die Nachrichten von Natur aus nicht sehr vertrauenswürdig.


Um vollständig zu sein, Sie könnten Ihre lokale begehen Geschichte um umschreiben zu reflektieren , was Sie wollen, wie von sykora vorgeschlagen (mit einer gewissen Fütterungsmaterial und Reset --hard, Keuchen!)

Sobald Sie jedoch Ihren überarbeiteten Verlauf erneut veröffentlichen (mit einem git push origin +master:master, dem +Zeichen, das den Push erzwingt, auch wenn dies nicht zu einem "Schnellvorlauf" -Commit führt), können Probleme auftreten .

Auszug aus dieser anderen SO-Frage:

Ich habe tatsächlich einmal mit --force in das git.git-Repository gepusht und wurde von Linus BIG TIME beschimpft. Es wird viele Probleme für andere Menschen schaffen. Eine einfache Antwort lautet "Tu es nicht".


gute Antwort. Wissen Sie, ob Sie jetzt bereits gepusste Commit-Nachrichten in neueren Versionen von git ändern können? Hat sich etwas geändert, seit dies in '09 veröffentlicht wurde?
David West

@DavidWest gilt das gleiche Prinzip: Sie können Ihre Historie neu schreiben und einen Push erzwingen.
VonC

2
Wenn Sie Commits ändern / neu festlegen, ändern sich die Commit-IDs (hexadezimale Hashes im Git-Index) zwangsläufig. Dies bedeutet, dass die bearbeiteten Commits anders behandelt werden als ihre alten Commits in der Git-VCS-Historie. Das heißt, wenn Ihre Entwickler-Teammitglieder die alten Commits leider bereits abgerufen haben, müssen sie die bearbeiteten neuen Commits abrufen und in ihren lokalen Arbeitskopien eine Zusammenführung zwischen dem alten und dem neuen Commit durchführen.
Shigerello

1
Es ist besser, bearbeitete Commits erneut zu pushen, um es Ihren Kollegen zu erleichtern, und damit die Notwendigkeit der Zusammenführung in den Arbeitskopien der Kollegen zu beseitigen.
Shigerello

28

Derzeit könnte ein Git-Ersatz den Trick machen.

Im Detail: Erstellen Sie einen temporären Arbeitszweig

git checkout -b temp

Zum Ersetzen auf das Commit zurücksetzen

git reset --hard <sha1>

Ändern Sie das Commit mit der richtigen Nachricht

git commit --amend -m "<right message>"

Ersetzen Sie das alte Commit durch das neue

git replace <old commit sha1> <new commit sha1>

Geh zurück zu dem Zweig, in dem du warst

git checkout <branch>

temporären Zweig entfernen

git branch -D temp

drücken

guess

getan.


11
@ Jonah: Ich erhalte die Meldung "Alles auf dem neuesten Stand", wenn ich versuche, auf den Remote-Zweig zu pushen
Simon Kagwi,

1
Wie in einer anderen Antwort erwähnt: Verwenden Sie rebase -i mit reword. Und es wird die Geschichte neu schreiben.
Sylvain

Vielen Dank für die Lösung, die ich gesucht habe. Du sparst meine Zeit!
Tomasz Kuter

1
@ Jonah - Ich habe ein Problem ... Ihre Lösung hat meine Commit-Protokolle lokal aktualisiert, jedoch nicht remote. Wie schiebe ich sie dorthin?
Tomasz Kuter

1
@TomaszKuter, ich hatte das gleiche Problem wie du. Meine Festschreibungsnachricht wurde nicht remote aktualisiert. Ich habe es mithilfe der folgenden Hilfe von GitHub gelöst: help.github.com/articles/changing-a-commit-message . Befolgen Sie die Anweisungen: Ändern der Nachricht älterer oder mehrerer Festschreibungsnachrichten. Dies ist im Grunde die Antwort von user987419 von unten. Wenn Sie die Festschreibungsnachricht bereits geändert haben, können Sie sie auswählen und speichern, ohne sie erneut ändern zu müssen.
Evaldeslacasa

19

Sie können git rebase -i'i' (für den Zweig, von dem Sie verzweigt haben) für interaktive Zwecke verwenden .

Ersetzen Sie den pickneben dem Commit-Kommentar, den Sie ändern möchten, durch r(oder reword), speichern und beenden Sie ihn. Anschließend können Sie die Bearbeitung vornehmen.

git push noch einmal und du bist fertig!


1
Dies erlaubt es nicht, Nachrichten bei Zusammenführungs-Commits zu bearbeiten. Ist das mit einer Variante dieses Befehls möglich?
Andrew Mao

1
Versuchen Sie das -pArgument, rebasewelche pReserven verschmelzen.
Kaktus

3
Ich mag dieses Verfahren, habe aber die Antwort zunächst nicht ganz verstanden. Für den Fall, dass jemand Hilfe benötigt, bietet die Githulb-Hilfeseite gute Informationen dazu: help.github.com/articles/changing-a-commit-message
evaldeslacasa

15

Angenommen, Sie haben einen Baum wie diesen:

dd2e86 - 946992 - 9143a9 - a6fd86 - 5a6057 [master]

Zunächst checkoutein temporärer Zweig:

git checkout -b temp

Beim tempVerzweigen reset --hardzu einem Commit, dessen Nachricht Sie ändern möchten (z. B. ist dieses Commit 946992):

git reset --hard 946992

Verwenden Sie amenddiese Option , um die Nachricht zu ändern:

git commit --amend -m "<new_message>"

Danach sieht der Baum folgendermaßen aus:

dd2e86 - 946992 - 9143a9 - a6fd86 - 5a6057 [master]
           \
            b886a0 [temp]

Verwenden Sie dann cherry-pickalle Commits, die vor 946992von masterto liegen, tempund legen Sie sie fest, amendwenn Sie auch ihre Nachrichten ändern möchten:

git cherry-pick 9143a9
git commit --amend -m "<new_message>
...
git cherry-pick 5a6057
git commit --amend -m "<new_message>

Der Baum sieht jetzt so aus:

dd2e86 - 946992 - 9143a9 - a6fd86 - 5a6057 [master]
               \
                b886a0 - 41ab2c - 6c2a3s - 7c88c9 [temp]

Drücken Sie nun den temporären Zweig zwangsweise auf Remote:

git push --force origin temp:master

Der letzte Schritt: Zweig masterauf lokaler Ebene löschen , git fetch originZweig mastervom Server abrufen, dann zu Zweig wechseln und Zweig masterlöschen temp.

Jetzt werden sowohl Ihre lokalen als auch Ihre Remote-Nachrichten alle Nachrichten aktualisiert.


5

In unserem Shop habe ich die Konvention eingeführt, erkennbar benannte kommentierte Tags zu Commits mit falschen Nachrichten hinzuzufügen und die Anmerkung als Ersatz zu verwenden.

Auch wenn dies Leuten, die gelegentliche "Git Log" -Befehle ausführen, nicht hilft, bietet es uns die Möglichkeit, falsche Bug-Tracker-Referenzen in den Kommentaren zu beheben, und alle meine Build- und Release-Tools verstehen die Konvention.

Dies ist offensichtlich keine generische Antwort, aber es könnte etwas sein, das die Leute in bestimmten Gemeinschaften übernehmen können. Ich bin sicher, wenn dies in größerem Maßstab verwendet wird, kann irgendwann eine Art Porzellanträger dafür auftauchen ...


3
"Git Notes" könnten einen ähnlichen Zweck erfüllen
Christian Goetze

2

(Von http://git.or.cz/gitwiki/GitTips#head-9f87cd21bcdf081a61c29985604ff4be35a5e6c0 )

Wie man Commits ändert, ist tiefer in der Geschichte

Da der Verlauf in Git unveränderlich ist, muss der Verlauf aus dem geänderten Festschreiben und Weiterleiten neu geschrieben werden, um etwas anderes als das letzte Festschreiben (Festschreiben, das kein Zweigkopf ist) zu korrigieren.

Sie können dafür StGIT verwenden, den Zweig bei Bedarf initialisieren, die Festschreibung für das zu ändernde Commit aufheben, bei Bedarf darauf zugreifen, eine Änderung vornehmen und den Patch aktualisieren (mit der Option -e, wenn Sie die Commit-Nachricht korrigieren möchten), und dann drücken alles und stg begehen.

Oder Sie können Rebase verwenden, um dies zu tun. Erstellen Sie einen neuen temporären Zweig, spulen Sie ihn mit git reset --hard auf das Commit zurück, das Sie ändern möchten, ändern Sie dieses Commit (es würde oben auf dem aktuellen Kopf stehen) und setzen Sie dann den Zweig über git rebase --onto neu auf das geänderte Commit.

Oder Sie können git rebase --interactive verwenden, das verschiedene Modifikationen wie Patch-Neuordnung, Reduzieren, ...

Ich denke, das sollte deine Frage beantworten. Beachten Sie jedoch, dass wenn Sie gedrückt Code zu einem Remote - Repository und die Leute von ihm gezogen haben, dann wird dies zu vermasseln ihren Code Geschichten gehen, sowie die Arbeit , die sie getan haben. Also mach es vorsichtig.


Gute Antwort in der Theorie, mächtig gefährlich in der Praxis: siehe stackoverflow.com/questions/253055#432518
VonC

0

Wenn Sie Git-Erweiterungen verwenden: Gehen Sie zum Festschreibungsbildschirm. Unten sollte ein Kontrollkästchen mit der Aufschrift "Commit ändern" angezeigt werden (siehe unten):

Geben Sie hier die Bildbeschreibung ein


@ KrunalPandya ja, oder drücken Sie einfach Commit & Push
Batsheva
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.