Ripristina una serie di commit in git


127

Come posso ripristinare una serie di commit in git? Osservando la documentazione di gitrevisions , non riesco a vedere come specificare l'intervallo di cui ho bisogno. Per esempio:

A -> B -> C -> D -> E -> HEAD

Voglio fare l'equivalente di:

git revert B-D

dove il risultato sarebbe:

A -> B -> C -> D -> E -> F -> HEAD

dove F contiene il contrario di BD incluso.


Verso la fine della pagina gitrevisions (7), c'è una sezione intitolata "SPECIFICARE GAMMA". In che modo ciò che desideri differisce da ciò che è descritto lì?
Gareth McCaughan,

2
La pagina di gitrevisions suggerisce che 'git ripristina A..D' farà quello che voglio. Tuttavia, quando provo a visualizzare l'errore "fatale: impossibile trovare 'A..D'"
Alex Spurling,

Risposte:


172

Quale versione di Git stai usando?

Il ripristino di più commit è supportato solo in Git1.7.2 +: vedere " Ripristino di un vecchio commit utilizzando il ripristino più volte. " Per ulteriori dettagli.
La git revertpagina man corrente è solo per l' attuale versione Git (1.7.4+).


Come riporta l' OP Alex Spurling nei commenti:

L'aggiornamento alla 1.7.4 funziona correttamente.
Per rispondere alla mia domanda, questa è la sintassi che stavo cercando:

git revert B^..D 

B^significa "il primo commit genitore di B": che consente di includere Bnel ripristino.
Vedi " git rev-parseSPECIFICARE la sezione REVISIONI " che include la sintassi <rev>^, ad esempioHEAD^ : vedi di più in " Che cosa significa il carattere caret ( ^)? ")

Si noti che ogni commit ripristinato viene eseguito il commit separatamente.

Henrik N chiarisce nei commenti :

git revert OLDER_COMMIT^..NEWER_COMMIT

Come mostrato di seguito, puoi ripristinare senza impegnarti subito:

git revert -n OLDER_COMMIT^..NEWER_COMMIT
git commit -m "revert OLDER_COMMIT to NEWER_COMMIT"

1
Grazie, questa era la risposta. L'aggiornamento alla 1.7.4 funziona correttamente. Per rispondere alla mia domanda, questa è la sintassi che stavo cercando: git ripristina B ^ .. D
Alex Spurling

genio. Grazie. Non mi era venuto in mente che devo ripristinare i commit in ordine inverso per applicare le patch, duh. Questo comando mostra la strada.
Tim Abell,

5
Mi riferisco spesso a questa risposta e mi ci vuole sempre un po 'di tempo per capire l'ordine. Quindi, per aiutare il mio futuro io:git revert OLDER_COMMIT^..NEWER_COMMIT
Henrik N,

2
cosa significa ^?
Dustin Getz,

1
@DustinGetz primo genitore: vedi git-scm.com/docs/gitrevisions : "Un suffisso ^per un parametro di revisione indica il primo genitore di quell'oggetto commit".
VonC,

15

Se vuoi ripristinare l'intervallo di commit da B a D (almeno nella versione 2 di git) in un singolo commit, puoi farlo

 git revert -n B^..D

Ciò ripristina le modifiche apportate dai commit dal commit principale di B (escluso) al commit D (incluso), ma non crea alcun commit con le modifiche ripristinate. Il ripristino modifica solo l'albero di lavoro e l'indice.

Non dimenticare di confermare le modifiche dopo

 git commit -m "revert commit range B to D"

Puoi anche ripristinare più commit non correlati in un singolo commit, usando lo stesso metodo. per esempio per ripristinare B e D ma non C

 git revert -n B D
 git commit -m "Revert commits B and D"

Riferimento: https://www.kernel.org/pub/software/scm/git/docs/git-revert.html

Grazie Honza Haering per la correzione


3
git revert -n B..Dnon ripristina il commit B, ma solo C e D. git revert -n B^..Dripristina anche B.
Honza Haering,

secondo la documentazione git che fa. riferimento nel post
Ramast

1
Se fai riferimento a questo esempio (che a mio avviso è un po 'confuso) nel riferimento git revert -n master~5..master~2:, dice il quinto ultimo commit incluso. Ma in master~5realtà è il sesto commit più recente. Vedi la selezione delle revisioni nei documenti git per informazioni dettagliate sulla ..notazione :-)
Honza Haering,

6

Fare git revert OLDER_COMMIT^..NEWER_COMMITnon ha funzionato per me.

Ho usato git revert -n OLDER_COMMIT^..NEWER_COMMITe tutto va bene. Sto usando la versione git 1.7.9.6.


Ho avuto lo stesso problema e risolto usando -n, ma dovresti lasciare ^ con OLDER_COMMIT (git ripristina -n OLDER_COMMIT ^ .. NEWER_COMMIT).
FeelGood

@FeelGood perché dovresti lasciare il ^?
Orlando,

Avevo la storia A -> B -> C e l'obiettivo era di ripristinare B e C. Quando eseguivo "git revert -n B..C", solo C veniva ripristinato. Quando ho usato 'git revert -n B ^ .. C', git ha ripristinato entrambi i commit. Forse ho fatto qualcosa di sbagliato.
FeelGood

bene, devo provarlo ma penso che nel mio caso abbia funzionato bene (a meno che non stia ripristinando un intervallo di 1 commit lol) modificherò la risposta per includere il ^. grazie
Orlando,

2
L' opzione -no --no-commitripristinerà tutte le modifiche nell'intervallo in un singolo commit, invece di creare un commit di ripristino per ogni commit nell'intervallo. Il risultato finale è lo stesso, come in, le stesse modifiche verranno ripristinate. Dipende solo da come vuoi che sia la tua cronologia git.
Dennis,

0

Utilizzare git rebase -iper schiacciare i relativi commit in uno. Quindi hai solo un commit da ripristinare.


7
Se usi git rebase, puoi semplicemente rimuovere i commit. Penso che ci sia un motivo per non ribadire, come voler mantenere SHA1 di commit F lo stesso.
Paŭlo Ebermann,

5
In alternativa, schiaccia i commit di ripristino in uno.
aeosynth,
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.