Annulla un particolare commit in Git che è stato trasferito a repository remoti


789

Qual è il modo più semplice per annullare un particolare commit che è:

  • non nella testa o nella TESTA
  • È stato inviato al telecomando.

Perché se non è l'ultimo commit,

git reset HEAD

non funziona E poiché è stato inviato a un telecomando,

git rebase -i

e

git rebase --onto

causerà qualche problema nei telecomandi.

Inoltre, non voglio davvero modificare la cronologia. Se c'era un codice errato, era presente nella storia e può essere visto. Lo voglio solo nella copia di lavoro e non mi dispiace un commit di unione inversa.

In altre parole, qual è l' equivalente Git dei seguenti comandi svn:

svn merge -r 303:295 http://svn.example.com/repos/calc/trunk

che rimuove tutte le modifiche da 295 a 302 unendo in modo inverso tutte le modifiche in tali revisioni, come un nuovo commit.

svn merge -c -302 ^/trunk

che annulla il commit 302, ovviamente aggiungendo un altro commit che inverte le modifiche da quel rispettivo commit.

Ho pensato che dovrebbe essere un'operazione abbastanza semplice in Git e un caso d'uso abbastanza comune. Cos'altro ha a che fare il commit atomico?

Abbiamo una messa in scena temporanea e tutti per garantire che i commit siano perfettamente atomici, non dovresti essere in grado di annullare facilmente uno o più di questi commit atomici?

Risposte:


1211

Identifica l'hash del commit, usando git log, quindi usa git revert <commit>per creare un nuovo commit che rimuove queste modifiche. In un certo senso, git revertè il contrario di git cherry-pick: quest'ultimo applica la patch a un ramo che lo manca, il primo lo rimuove da un ramo che lo possiede.


237
E usa l'opzione -n ​​se vuoi indietro il codice, ma non
esegui

17
Che cosa fa l'opzione "m"? Ho provato git a ripristinare 8213f7d ma ho ottenuto questo: errore: Commit 8213f7dad1ed546b434a0d8a64cb783b530a5a30 è un'unione ma non è stata fornita alcuna opzione -m. fatale: ripristino fallito
Malcolm

10
Per ripristinare un'unione: git revert -m 1 <hash>
brunozrk

31
Un avvertimento per chiunque desideri ripristinare un'unione: git revert annulla tutte le modifiche ai dati (ovvero, le modifiche al file verranno ripristinate), ma l'unione rimane nella cronologia. Per questo motivo, se si tenta di unire nuovamente lo stesso ramo in un secondo momento, questo non includerà alcun commit dal ramo di fusione prima dell'unione ripristinata. Molto probabilmente questo non è quello che vuoi. Per unire nuovamente completamente il ramo, devi prima ripristinare il commit in cui hai ripristinato l'unione originale. Ulteriori informazioni qui: kernel.mirrors.pair.com/pub/software/scm/git/docs/howto/…
etreworgy

3
Il link nel commento di @etreworgy è 404. Sospetto che questa sia una versione aggiornata del link: kernel.org/pub/software/scm/git/docs/howto/…
Tim Smith

368

Non mi piace il commit automatico che git revertfa, quindi questo potrebbe essere utile per alcuni.

Se si desidera solo che i file modificati non siano il commit automatico , è possibile utilizzare--no-commit

% git revert --no-commit <commit hash>

che è lo stesso del -n

% git revert -n <commit hash>

9
Potresti anche fare git reset HEAD~1 --softse sei già tornato senza-n
Daniel

1
Ma git reset HEAD~nnon risolverà l'annullamento di alcun commit non continuamente raggiungibile dalla testa. La query è di ripristinare qualsiasi commit particolare.
sangeethkumarp,

Ho usato questa soluzione ma ho riscontrato un conflitto nel mezzo del ripristino. Dopo aver risolto il conflitto, ho fatto git revert --continuesecondo le istruzioni. Ha funzionato, ma purtroppo ha impegnato i risultati. Forse dovevo farlo git revert --no-commit --continue.
mareoraft

1
@sangeethkumarp il commento di Daniel è un ulteriore passo che puoi fare dopo il git revert, se hai dimenticato il -n; perché a quel punto l'ultimo commit è l'inversione, quindi il soft reset annullerà quel commit ma non le modifiche al codice associate del ripristino
Oliver

@Daniel ha fornito soluzioni di commento per me Grazie mille '' git reset HEAD ~ 1 --soft ''
Md. Abu Sayed

41

Poiché è già stato inserito, non è necessario manipolare direttamente la cronologia. git revertripristinerà le modifiche specifiche da un commit utilizzando un nuovo commit, in modo da non manipolare la cronologia dei commit.


1

Se il commit che si desidera ripristinare è un commit unito (è stato già unito), è necessario selezionare l' opzione -m 1o -m 2come mostrato di seguito. Ciò consentirà a git di sapere quale commit padre del commit unito utilizzare. Maggiori dettagli possono essere trovati QUI .

  • git revert <commit> -m 1
  • git revert <commit> -m 2
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.