Come posso modificare un messaggio di commit errato in git (che ho inviato)?


152

Voglio modificare un messaggio di commit più in profondità nella storia e ho spinto molti nuovi commit.

Come posso modificare il messaggio di commit? È possibile?

Risposte:


125

Il messaggio di Linus Torvalds potrebbe rispondere alla tua domanda:

Modifica / modifica i vecchi messaggi di commit

Risposta breve: non puoi (se premuto).


extract (Linus si riferisce a BitKeeper come BK):

Nota a margine, solo per interesse storico: in BK potresti.

E se ci sei abituato (come ero io) era davvero abbastanza pratico. Vorrei applicare una patch-bomb di Andrew, notare che c'era qualcosa che non andava e modificarlo prima di espellerlo.

Avrei potuto fare lo stesso con Git. Sarebbe stato abbastanza facile fare in modo che il messaggio di commit non facesse parte del nome e garantire comunque che la cronologia non fosse toccata, e consentire la "correzione dei commenti in seguito".

Ma non l'ho fatto.

Parte di essa è puramente "coerenza interna". Git è semplicemente un sistema più pulito grazie a tutto ciò che è protetto da SHA1 e tutti gli oggetti trattati allo stesso modo, indipendentemente dal tipo di oggetto. Sì, ci sono quattro diversi tipi di oggetti, e sono tutti davvero diversi, e non possono essere usati allo stesso modo, ma allo stesso tempo, anche se la loro codifica potrebbe essere diversa su disco, concettualmente funzionano tutti esattamente lo stesso.

Ma la coerenza interna non è in realtà una scusa per essere poco flessibile, e chiaramente sarebbe molto flessibile se potessimo solo correggere gli errori dopo che si sono verificati. Quindi non è un argomento davvero forte.

La vera ragione per cui git non ti consente di cambiare il messaggio di commit finisce per essere molto semplice: in questo modo, puoi fidarti dei messaggi. Se hai permesso alle persone di modificarle in seguito, i messaggi non sono intrinsecamente molto affidabili.


Per essere completo, è possibile riscrivere la cronologia di commit locale al fine di riflettere ciò che si desidera, come suggerito da Sykora (con alcuni rebase e reset --hard, gasp!)

Tuttavia, una volta che si pubblica la vostra storia rivisto ancora una volta (con una git push origin +master:master, il +segno costringendo la spinta a verificarsi, anche se non si traduca in un "fast-forward" commit) ... si potrebbe ottenere in qualche guaio .

Estratto da questa altra domanda SO:

In realtà una volta ho spinto con --force nel repository git.git e sono stato sgridato da Linus BIG TIME. Creerà molti problemi per altre persone. Una semplice risposta è "non farlo".


buona risposta. Sai se ora sei in grado di cambiare i messaggi di commit già inseriti nelle versioni più recenti di git? È cambiato qualcosa da quando è stato pubblicato nel '09?
David West,

@DavidWest vale lo stesso principio: puoi riscrivere la tua storia e forzare una spinta.
VonC,

2
Per rendere le cose più specifiche, se si modificano / rebase i commit, i loro identificativi di commit (hash esadecimali nell'indice git) cambiano inevitabilmente; significa che i commit modificati sono trattati in modo diverso dai loro vecchi commit nella cronologia di Git VCS. Detto questo, se i membri del tuo team di sviluppo purtroppo hanno già eseguito i vecchi commit, sono obbligati a eseguire il pull dei nuovi e modificati ed eseguire una fusione tra vecchio e nuovo nelle loro copie di lavoro locali.
Shigerello,

1
È meglio spingere nuovamente i commit modificati per comodità dei tuoi colleghi, eliminando così favorevolmente la necessità di unire le copie di lavoro dei colleghi.
Shigerello,

28

Attualmente un sostituto git potrebbe fare il trucco.

Nel dettaglio: creare un ramo di lavoro temporaneo

git checkout -b temp

Ripristinare il commit per sostituire

git reset --hard <sha1>

Modifica il commit con il messaggio giusto

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

Sostituisci il vecchio commit con quello nuovo

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

torna al ramo dove eri

git checkout <branch>

rimuovere il ramo temporaneo

git branch -D temp

spingere

guess

fatto.


11
@Jonah: ricevo un messaggio "Tutto aggiornato" quando provo a spingere al ramo remoto
Simon Kagwi,

1
Come menzionato in un'altra risposta: usa rebase -i con reword. E riscriverà la storia.
Sylvain,

Grazie per la soluzione che stavo cercando. Mi risparmia tempo!
Tomasz Kuter,

1
@Jonah - Ho un problema ... la tua soluzione ha aggiornato i miei log di commit localmente, ma non da remoto. Come spingerli lì?
Tomasz Kuter,

1
@TomaszKuter, ho avuto lo stesso problema come te. Il mio messaggio di commit non è stato aggiornato in remoto. L'ho risolto utilizzando il seguente aiuto di GitHub: help.github.com/articles/changing-a-commit-message . Segui la sezione: Modifica del messaggio di messaggi di commit più vecchi o multipli. È fondamentalmente la risposta dal basso fornita dall'utente987419 Se hai già modificato il messaggio di commit, puoi scegliere e salvare senza doverlo cambiare di nuovo.
evaldeslacasa,

19

È possibile utilizzare git rebase -i(contro il ramo da cui si è ramificato) 'i' per interattivo.

Sostituisci il pickprossimo con il commento di commit che desideri modificare r(o reword), salva ed esci e, facendo ciò, sarai in grado di effettuare la modifica.

git push ancora una volta e il gioco è fatto!


1
Ciò non consente di modificare i messaggi in commit unione. È possibile con qualche variante di questo comando?
Andrew Mao,

1
Prova l' -pargomento di rebasequali priserve si fondono.
Cactus,

3
Mi piace questa procedura, ma all'inizio non ho capito bene la risposta. Nel caso in cui qualcuno abbia bisogno di aiuto, la pagina della Guida di Githulb offre buone informazioni al riguardo: help.github.com/articles/changing-a-commit-message
evaldeslacasa

15

Supponiamo di avere un albero come questo:

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

Innanzitutto, checkoutun ramo temporaneo:

git checkout -b temp

Sul tempramo, reset --harda un commit che si desidera modificare il suo messaggio (ad esempio, quel commit è 946992):

git reset --hard 946992

Utilizzare amendper modificare il messaggio:

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

Dopodiché l'albero apparirà così:

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

Quindi, cherry-picktutto il commit che precede 946992da mastera tempe li commette, utilizzare amendse si desidera modificare anche i loro messaggi:

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

L'albero ora appare così:

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

Ora forza spingi il ramo temporaneo sul telecomando:

git push --force origin temp:master

Il passaggio finale, eliminare il ramo mastersu locale, git fetch originper estrarre il ramo masterdal server, quindi passare al ramo mastered eliminare il ramo temp.

Ora sia il tuo locale che il tuo remoto avranno tutti i messaggi aggiornati.


5

Nel nostro negozio, ho introdotto la convenzione di aggiungere tag annotati con nome riconoscibile per eseguire il commit con messaggi errati e utilizzare l'annotazione come sostituzione.

Anche se questo non aiuta le persone che eseguono comandi "git log" casuali, ci fornisce un modo per correggere i riferimenti errati di tracker dei bug nei commenti e tutti i miei strumenti di compilazione e rilascio comprendono la convenzione.

Questa ovviamente non è una risposta generica, ma potrebbe essere qualcosa che la gente può adottare all'interno di comunità specifiche. Sono sicuro che se questo viene utilizzato su una scala più ampia, potrebbe sorgere una sorta di supporto in porcellana, alla fine ...


3
"git notes" potrebbe avere uno scopo simile
Christian Goetze,

2

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

Come cambiare si impegna più a fondo nella storia

Poiché la cronologia in Git è immutabile, la correzione di qualsiasi cosa tranne il commit più recente (commit che non è la diramazione) richiede che la cronologia venga riscritta dal commit modificato e inoltra.

È possibile utilizzare StGIT per questo, inizializzare il ramo se necessario, annullare il commit fino al commit che si desidera modificare, pop su di esso se necessario, apportare una modifica quindi aggiornare la patch (con l'opzione -e se si desidera correggere il messaggio di commit), quindi premere tutto e stg si impegnano.

Oppure puoi usare rebase per farlo. Crea un nuovo ramo temporaneo, riavvolgi il commit che vuoi modificare usando git reset --hard, cambia quel commit (sarebbe in cima alla testa corrente), quindi rinnova il ramo in cima al commit modificato, usando git rebase --onto.

Oppure puoi usare git rebase --interactive, che consente varie modifiche come riordinare le patch, comprimere, ...

Penso che dovrebbe rispondere alla tua domanda. Tuttavia, tieni presente che se hai trasferito il codice in un repository remoto e le persone ne hanno tratto, questo rovinerà la loro cronologia del codice, così come il lavoro che hanno svolto. Quindi fallo con attenzione.


Buona risposta, in teoria, potente pericolosa in pratica: vedi stackoverflow.com/questions/253055#432518
VonC

0

Se stai usando le estensioni Git: vai nella schermata Commit, ci dovrebbe essere una casella di controllo che dice "Modifica Commit" in basso, come puoi vedere di seguito:

inserisci qui la descrizione dell'immagine


@KrunalPandya sì, o semplicemente premi commit e push
batsheva
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.