git selettiva ripristina le modifiche locali da un file


149

Nel mio repository git che sta monitorando un repository svn ho apportato una serie di modifiche a un singolo file.

Ora voglio ripristinare quelle modifiche (come svn revert), ma solo parti del file.

Voglio essere in grado di visualizzare le differenze sul file, scartare (ripristinare) le modifiche che non voglio e conservare le modifiche che desidero.

il

git add -i 

il comando sembra avere un'opzione per farlo, ma non voglio ancora metterlo in scena.

Risposte:


91

Puoi farlo direttamente con git checkout -p. Vedi la risposta di Daniel Stutzbach di seguito.


Vecchia risposta (prima checkout -pdell'introduzione):

Puoi farlo in questo modo:

git add -i

(seleziona i pezzi che vuoi conservare)

git commit -m "tmp"

Ora hai un commit con solo le modifiche che vuoi mantenere e il resto non è in scena.

git reset --hard HEAD

A questo punto, le modifiche senza commit sono state scartate, quindi hai una directory di lavoro pulita, con le modifiche che vuoi mantenere impegnate in cima.

git reset --mixed HEAD^

Ciò rimuove l'ultimo commit ('tmp'), ma mantiene le modifiche nella directory di lavoro, non messe in scena.

EDIT: sostituito --softcon --mixed, per ripulire l'area di stadiazione.


questo impegnerà le modifiche che voglio mantenere non è vero? Non voglio ancora impegnare tali modifiche. mm forse sto prendendo gli impegni troppo sul serio. Forse dovrei rilassarmi ora dato che è tutto in un repository locale. tra l'altro cosa reimposta git --soft HEAD ^?
Pradeep,

"git reset --soft HEAD ^" annulla un commit nel senso che mantiene la directory e l'indice funzionanti come prima e sposta indietro il ramo corrente di un commit.
Jakub Narębski,

Grazie Jakub. Paolo perché qui sarebbe necessario un reset software per la testa - 1? il commit parziale e l'hard reset dovrebbero essere sufficienti non è per mantenere alcune modifiche e scartarne altre?
Pradeep,

1
La risposta di Daniel di seguito è molto semplice e sembra il modo giusto per farlo.
Umang,

309

Credo che tu possa farlo più semplicemente con:

git checkout -p <optional filename(s)>

Dalla manpage:

   −p, −−patch
       Interactively select hunks in the difference between the <tree−ish>
       (or the index, if unspecified) and the working tree. The chosen
       hunks are then applied in reverse to the working tree (and if a
       <tree−ish> was specified, the index).
       This means that you can use git checkout −p to selectively discard
       edits from your current working tree.

1
Inoltre, se non si desidera farlo in modo selettivo, è possibile utilizzare "git checkout - <file> ..." per annullare le modifiche.
db42,

Si occupa di directory?
bbum

1
Questo sembra fallire molto per me quando scarto le modifiche ("errore: patch fallito <file>", "errore: <file> patch non applicabile"). Stranamente riceverò quegli errori quando si usa l' aopzione in modalità patch per scartare un intero file, ma git checkout -- <file>funziona come previsto. Qualcuno sa perché?
chrnola,

Ho avuto questo errore alcune volte se il file era già stato patchato, quindi la patch interattiva non era aggiornata con le patch applicate al file corrente. È successo quando ho usato uno strumento gui come l'albero dei sorgenti se ho scartato un pezzo due volte per caso. La seconda volta produrrebbe quell'errore.
Phyatt,

3

È possibile eseguire git diffil file, salvare il diff risultante, modificarlo per rimuovere le modifiche che si desidera salvare, quindi eseguirlo patch -Rper annullare le differenze rimanenti.

git diff file.txt> patch.tmp
# edit patch.tmp per rimuovere gli hunk che vuoi conservare
patch -R <patch.tmp

Ho avuto 2 pezzi nel mio file di patch e ne ho rimosso uno. Non sono sicuro di quale sia il motivo, ma la patch -R continua a essere rifiutata con questo.
Pradeep,

2
Citi in un altro commento che git diffmostra l'intero file come modificato. Questo di solito accade quando hai salvato il file usando terminazioni di riga diverse rispetto a prima. Ciò provocherebbe anche il patchrifiuto del file patch. Suona come quello che potrebbe essere successo?
Greg Hewgill,

hai ragione. le terminazioni di riga vengono attivate ogni volta che utilizzo il comando patch. Sono su Windows e utilizzo Cream / Vim. Devo risolvere prima questo, credo.
Pradeep,

Non sono stato in grado di risolvere il problema con la patch su Windows. Anche se sono sicuro che funzioni, preferisco usare la ricetta di Paolo. Per l'amore di quei comandi interattivi di lavorare con i diff usando git add -i.
Pradeep,

3

Sembra che tu voglia

 git revert --no-commit $REVSISON 

È quindi possibile utilizzare

 git diff --cached

per vedere quali modifiche verranno apportate prima del commit (poiché il ripristino è solo un commit in una direzione in avanti che replica l'inverso di una modifica nel passato)

Se tu fossi con un repository Git puro, potresti, a seconda dei tuoi obiettivi, utilizzare interattivamente rebase ( git rebase -i) per tornare al commit che non ti è piaciuto e modificare il commit retroattivamente in modo che i cambiamenti che non ti piacciono non siano mai avvenuti , ma questo è generalmente solo se SAPI che non vorrai mai più vederlo.


Ho ripristinato come hai menzionato una revisione precedente (è corretto?) E ora git diff mostra solo l'intero file come modificato. Dovrebbe mostrare le modifiche che avevo fatto?
Pradeep,

1

Rileggendo la domanda, sembra che tu voglia ripristinare i cambiamenti che sono nel tuo albero di lavoro e non i cambiamenti che sono stati precedentemente commessi, ma alcune delle altre risposte fanno sembrare che la mia lettura potrebbe essere sbagliata. Puoi chiarire?

Se le modifiche sono solo nella tua copia di lavoro, il modo più semplice per farlo è mettere in scena le modifiche che desideri mantenere:

git add -i <file>

Quindi elimina le modifiche che non desideri mantenere verificando la versione dell'indice:

git checkout -- <file>

Quindi disimballare le modifiche se non si desidera che vengano ancora messe in scena:

git reset -- <file>

Questa ricetta ripristina solo le modifiche selezionate al file (o ai file specificati) e non crea alcun commit temporaneo che deve essere ripristinato.

Se si desidera applicare selettivamente solo alcune delle modifiche apportate nei commit precedenti, è possibile ripristinare prima un file a uno stato di commit precedente:

git reset <commit_before_first_unwanted_change> -- <file>

Quindi è possibile seguire la ricetta precedente git add -i <file>per mettere in scena le modifiche che si desidera conservare, git checkout -- <file>eliminare le modifiche indesiderate e git reset -- <file>"annullare la messa in scena" delle modifiche.


0

Le opzioni della riga di comando descritte nelle risposte qui sono utili quando il file si trova su un server a cui accedo tramite un terminale SSH. Tuttavia, quando il file si trova sul mio computer locale preferisco il seguente modo:

Apri il file nell'editor netbeans (che viene fornito con il supporto git). Netbeans mette segni rossi / verdi / blu ai numeri di riga per indicare dove gli oggetti sono stati eliminati / aggiunti / modificati (rispettivamente).

Facendo clic con il tasto destro su uno di questi segni è possibile annullare tale modifica. Inoltre, puoi fare clic con il pulsante destro del mouse sui segni rosso e blu per trovare la versione precedente in un popup.

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.