2010-04-12 20 views
50

Desidero ripristinare le modifiche apportate da un particolare commit solo a un determinato file.Ripristina le modifiche a un file in un commit

Posso usare il comando git revert per quello?

Qualsiasi altro modo semplice per farlo?

+0

Duplicato di http://stackoverflow.com/questions/215718/reset-or-revert-a-specific-file-to-a-specific-revision-using-git/215768 – koppor

+0

Strano ... perché il cambiamento dopo tutti quegli anni? – VonC

risposta

90

Il modo più pulito che ho visto di fare questo è descritto here

git show some_commit_sha1 -- some_file.c | git apply -R 

Simile alla risposta di VonC ma usando git show e git apply.

+2

Boom! Tu sei l'uomo. – yitznewton

+6

Ben fatto. La soluzione di script è esagerata per questo. Perché non ci può essere semplicemente git revert sha-1 filename? –

+0

Bello, ma anche VonCs non è male. Con entrambi c'è qualcosa da imparare ogni giorno in git :) – hakre

18

git revert è per tutti i contenuti del file all'interno di un commit.

per un singolo file, è possibile script it:

#!/bin/bash 

function output_help { 
    echo "usage: git-revert-single-file <sha1> <file>" 
} 

sha1=$1 
file=$2 

if [[ $sha1 ]]; then 
git diff $sha1..$sha1^ -- $file | patch -p1 
else 
output_help 
fi 

(Dalle git-shell-scripts utilità dal smtlaissezfaire)


Nota:

un altro modo è described here se avete ancora commetti la tua modifica attuale.

git checkout -- filename 

git checkout ha alcune opzioni per un file, modificando il file da HEAD, sovrascrivendo la modifica.


Dropped.on.Caprica menzioni in the comments:

È possibile aggiungere un alias a git in modo da poter fare git revert-file <hash> <file-loc> e avere quel file specifico essere ripristinato.
Vedere this gist.

[alias] 
    revert-file = !sh /home/some-user/git-file-revert.sh 
+0

Giusto per aggiungere alla discussione qui, è possibile aggiungere un alias a git in modo da poter eseguire 'git revert-file ' e fare in modo che il file specifico venga ripristinato. Ho sollevato da questa risposta (anche se dovevo fare un paio di modifiche per funzionare correttamente). Puoi trovare una copia del mio script '.gitconfig' e modificato qui: https://gist.github.com/droppedoncaprica/5b67ec0021371a0ad438 –

+0

@ Dropped.on.Caprica buon punto. L'ho incluso nella risposta per maggiore visibilità. – VonC

+0

Grazie! Ho aggiornato un po 'il tuo post per adattarlo all'utilizzo corretto, ma per il resto roba buona! –

12

vorrei semplicemente utilizzare l'opzione --no-commit per git-revert e quindi rimuovere i file che non si desidera per conversione dall'indice prima infine commetterlo. Ecco un esempio che mostra come ripristinare facilmente solo le modifiche foo.c nel secondo più recente commettere:

$ git revert --no-commit HEAD~1 
$ git reset HEAD 
$ git add foo.c 
$ git commit -m "Reverting recent change to foo.c" 
$ git reset --hard HEAD 

I primi git-reset "unstages" tutti i file, in modo da poter poi aggiungere indietro solo quello file che abbiamo voglio ripristinato. L'ultimo git-reset --hard elimina il file rimanente che non vogliamo conservare.

15

ammesso che sia ok per cambiare la storia impegnarsi, ecco un flusso di lavoro per annullare le modifiche in un unico file in una precedente commit:

Per esempio, si vuole annullare le modifiche in 1 lima (badfile.txt) a commettere aaa222 :

aaa333 Good commit 
aaa222 Problem commit containing badfile.txt 
aaa111 Base commit 

Rebase sulla base commettere, modificare il problema commettere, & continuare.

1) Avviare rebase interattivo:

git rebase -i aaa111 

2) Mark il problema commit per la modifica nell'editor cambiando pick a e (per la modifica):

e aaa222 
pick aaa333 

3) Ripristinare modifiche il file non valido:

git show -- badfile.txt | git apply -R 

4) Aggiungere le modifiche & modificare il commit:

git add badfile.txt 
git commit --amend 

5) terminare il rebase:

git rebase --continue 
+0

Voglio solo sottolineare che questo presuppone che tu possa modificare la cronologia git. Alcune risposte sopra creano un nuovo commit che inverte la particolare modifica senza modificare la cronologia, che non è sempre possibile/permesso. – angularsen

+0

Questa soluzione è stata la mia scelta e ha funzionato perfettamente! Il rebase interattivo può fare molta magia :) Grazie! –

1

molto più semplice:

git reset HEAD^ path/to/file/to/revert 

poi

git commit --amend 

e poi

git push -f 

il file è andato e commit hash, messaggio, ecc è lo stesso.

+0

Per completezza, è necessario un passo 'git checkout - path/to/file/to/revert'? Inoltre, non è vero che l'hash è lo stesso in seguito, giusto? L'ultima frase potrebbe essere migliore di qualcosa del tipo: "Il risultato è che l'ultimo commit è sostituito da uno nuovo che differisce solo dal fatto che non contiene le modifiche al file ripristinato." – Kevin

Problemi correlati