Come rimuovere la messa in scena di un numero elevato di file senza eliminare il contenuto


454

Ho accidentalmente aggiunto molti file temporanei usando git add -A

Sono riuscito a disinstallare i file utilizzando i seguenti comandi e sono riuscito a rimuovere l'indice sporco.

git ls-files -z | xargs -0 rm -f
git diff --name-only --diff-filter=D -z | xargs -0 git rm --cached

I comandi precedenti sono elencati in git help rm. Ma purtroppo, anche i miei file sono stati eliminati durante l'esecuzione, anche se avevo fornito l'opzione cache. Come posso cancellare l'indice senza perdere il contenuto?

Inoltre sarebbe utile se qualcuno può spiegare come funziona questa operazione di tubazione.


8
rm -fnon è un comando git e non ha --cachedun'opzione. I tuoi file locali sono stati eliminati prima dell'esecuzione, git rmquindi non credo che tu possa legittimamente incolpare git rmnulla.
CB Bailey,

8
@sarat, ti preghiamo di considerare di cambiare la risposta corretta alla risposta altamente votata da Ian Maddox , in quanto nongit reset --hard è la risposta corretta ed eliminerà di fatto il contenuto. Questo confonderà gli utenti, come ho fatto io.
Marco Pashkov,

2
@sarat come dice Marco, continua. Questa pagina riceve molto traffico.
Ross,

@MarcoPashkov & Ross grazie ragazzi. Fatto.
Sarat,

Risposte:


986

git reset

Se tutto ciò che vuoi è annullare una corsa "git add" troppo zelante:

git reset

Le modifiche non verranno messe in scena e saranno pronte per essere aggiunte di nuovo come desideri.


NON CORRIRE git reset --hard.

Non solo metterà in scena i file aggiunti, ma annullerà tutte le modifiche apportate nella directory di lavoro. Se hai creato nuovi file nella directory di lavoro, non li elimineranno comunque.


15
Ti devo una pinta di birra Ian
DasBooten,

1
Trovo spesso che devo esibirmi git checkout -- *anche io
Den-Jason il

1
Hai risparmiato molti sforzi. Grazie amico
RajnikantDixit,

35

Se hai un repository incontaminato (o HEAD non è impostato) [1] potresti semplicemente

rm .git/index

Naturalmente, questo richiede di aggiungere nuovamente i file che si ha da aggiungere.


[1] Nota (come spiegato nei commenti) questo di solito accade solo quando il repository è nuovo di zecca ("incontaminato") o se non è stato effettuato alcun commit. Più tecnicamente, ogni volta che non c'è checkout o albero di lavoro.

Sto solo rendendo più chiaro :)


Sì, è più come cancellare l'indice creato stesso. La cosa buona è che non ho bisogno di reinizializzare git. Grazie!
sarat,

Sei sicuro che sia un'operazione sicura? Ho appena fatto questo (effettivamente spostato l'indice fuori strada) e ho messo in scena tutti gli altri file per l'eliminazione.
inger il

@inger "Se hai un repository incontaminato". Chiaramente non l'hai avuto.
Vede il

In realtà, mi chiedevo cosa intendevi per "pristine repo" (non mi sento fortunato neanche con google) .. Quindi in realtà intendevi un repo vuoto?
inger

1
@inger Accetto. Ho dovuto presumere che il PO avesse avuto questa situazione esatta - non lo specifica, ma la sua descrizione lascia la possibilità. Ad ogni modo, sto solo condividendo informazioni e non posso influenzare il voto :(. Ho aggiunto una parola di avvertimento al testo della risposta, nel caso in cui aiuti gli altri in futuro.
vedi

15

Utilizzare git reset HEADper ripristinare l'indice senza rimuovere i file. (Se si desidera ripristinare solo un determinato file nell'indice, è possibile utilizzare git reset HEAD -- /path/to/fileper farlo.)

L'operatore pipe, in una shell, prende il stdoutprocesso a sinistra e lo passa stdinal processo a destra. È essenzialmente l'equivalente di:

$ proc1 > proc1.out
$ proc2 < proc1.out
$ rm proc1.out

ma invece è $ proc1 | proc2, il secondo processo può iniziare a ottenere dati prima che il primo venga eseguito, e non è coinvolto alcun file reale.


ma su come usarlo con più file. Non ho mai eseguito il commit di questi file prima.
sarat,

3
Basta digitare git reset HEADsenza specificare nient'altro e reimposterà l'intero indice. È quindi possibile aggiungere nuovamente solo i file desiderati.
Ambra,

Ho ricevuto il seguente errore. Non ho mai commesso questi articoli prima. $ git reset HEAD fatal: ambiguous argument 'HEAD': unknown revision or path not in the working tree. Use '--' to separate paths from revisions
sarat,

1
Prova proprio git resetallora, senza il HEAD.
Ambra,

Ho già provato a finire nel seguente errore. $ git reset fatal: Failed to resolve 'HEAD' as a valid ref.
sarat,

9
git stash && git stash pop

2
Vorrei fare "git stash && git stash pop" in modo che anche lo stash venga eliminato. 'applica' lascerebbe lo stash nell'elenco degli stash.
chitti,

8

Se HEAD non è impostato (ovvero, non hai ancora eseguito il commit, ma non vuoi semplicemente saltare via .gitperché hai già impostato altre configurazioni repo che desideri mantenere), puoi anche fare

git rm -rf --cached .

per mettere in scena tutto. Questo è effettivamente lo stesso della soluzione sehe, ma evita di perdere tempo con gli interni di Git.


questo in realtà dice a Git di cancellare tutto nell'area cache.
Visionary Software Solutions

1
La cache è anche conosciuta come area di gestione temporanea, quindi non sono sicuro di cosa stai arrivando.
jjlin,

Da sehe, rm .git / index è molto pericoloso - assicurati di leggere la NOTA che ha su un repository nuovo di zecca! Questo è molto più sicuro per l'altro 99,999% delle volte. Non ho letto attentamente e ho dovuto spazzare via la mia copia di lavoro e ri-clonare dopo aver eseguito rm .git / index sulla mia copia di lavoro.
phpguru,

NON utilizzare questo comando! Cambierà TUTTO il progetto allo stato non tracciato (compresi quelli che non sono stati messi in scena). Questa non è una soluzione alla domanda originale. La soluzione corretta usando il comando 'git rm' è di specificare SOLO i file che si desidera non mettere in scena: git rm -rf --cached <file che si desidera mettere in scena>.
Monte Creasor,

Dovresti usare questo comando solo quando hai un nuovo repository senza ancora commit (questo è ciò che significa "HEAD non è impostato"), ma non vuoi semplicemente saltare via .gitperché hai impostato altri repository configurandoti voglio mantenere. Ho modificato per chiarire questo.
jjlin,

5

Attenzione: non utilizzare il seguente comando a meno che non si desideri perdere il lavoro senza commit!

L'uso git resetè stato spiegato, ma hai chiesto anche una spiegazione dei comandi inoltrati, quindi ecco:

git ls-files -z | xargs -0 rm -f
git diff --name-only --diff-filter=D -z | xargs -0 git rm --cached

Il comando git ls-fileselenca tutti i file che Git conosce. L'opzione -zimpone un formato specifico su di essi, il formato previsto da xargs -0, che quindi rm -fli invoca , il che significa rimuoverli senza verificare l'approvazione.

In altre parole, "elenca tutti i file che Git conosce e rimuovi la tua copia locale".

Quindi arriviamo a git diff, che mostra i cambiamenti tra le diverse versioni di elementi che Git conosce. Questi possono essere cambiamenti tra alberi diversi, differenze tra copie locali e copie remote e così via.
Come usato qui, mostra le modifiche non messe in scena; i file che hai modificato ma non hai ancora eseguito il commit. L'opzione --name-onlyindica che desideri solo i nomi dei file (completi) e --diff-filter=Dindica che sei interessato solo ai file eliminati. (Ehi, non abbiamo semplicemente cancellato un mucchio di roba?) Questo viene quindi reindirizzato al file che xargs -0abbiamo visto prima, che git rm --cachedli invoca , il che significa che vengono rimossi dalla cache, mentre l'albero di lavoro dovrebbe essere lasciato solo - tranne che hai appena rimosso tutti i file dall'albero di lavoro. Ora vengono rimossi anche dal tuo indice.

In altre parole, tutti i cambiamenti, messi in scena o non messi in scena, sono andati e il tuo albero di lavoro è vuoto. Fai un grido, controlla i tuoi file freschi dall'origine o dal remoto e ripeti il ​​tuo lavoro. Maledici il sadico che scrisse queste righe infernali; Non ho idea del perché qualcuno voglia fare questo.


TL; DR: hai appena nascosto tutto; ricominciare e utilizzare git resetda ora in poi.


2

Temo che la prima di quelle righe di comando venga eliminata incondizionatamente dalla copia di lavoro tutti i file presenti nell'area di gestione temporanea di git. Il secondo non ha messo in scena tutti i file che sono stati tracciati ma che ora sono stati eliminati. Sfortunatamente questo significa che avrai perso qualsiasi modifica non impegnata a quei file.

Se vuoi riportare la tua copia di lavoro e indicizzarla a come erano all'ultimo commit , puoi ( attentamente ) usare il seguente comando:

git reset --hard

Dico "attentamente" poiché git reset --hard annullerà le modifiche non confermate nella copia e nell'indice di lavoro. Tuttavia, in questa situazione sembra che tu voglia tornare allo stato al tuo ultimo commit, e le modifiche non confermate sono andate perse comunque.

Aggiornamento: dai tuoi commenti sulla risposta di Amber sembra che non hai ancora creato alcun commit (dato che HEAD non può essere risolto), quindi questo non aiuta, temo.

Per quanto riguarda il modo in cui funzionano quelle pipe: git ls-files -zed git diff --name-only --diff-filter=D -zentrambe producono un elenco di nomi di file separati dal byte 0. (Ciò è utile, poiché, a differenza delle newline, 0si garantisce che i byte non si verifichino nei nomi di file su sistemi simili a Unix.) Il programma xargsessenzialmente crea righe di comando dal suo input standard, per impostazione predefinita prendendo le righe dall'input standard e aggiungendole alla fine della riga di comando. L' -0opzione dice di prevedere un input standard separato da 0byte. xargspuò richiamare più volte il comando per utilizzare tutti i parametri dall'input standard, assicurandosi che la riga di comando non diventi mai troppo lunga.

Ad esempio, se si dispone di un file chiamato test.txt, con i seguenti contenuti:

hello
goodbye
hello again

... quindi il comando xargs echo whatever < test.txtinvocherà il comando:

echo whatever hello goodbye hello again

Non ho mai fatto alcun commit, quindi dirà che non riesco a risolvere HEAD. Cosa facciamo in tali situazioni. Grazie mille per aver spiegato dettagliatamente la pipa.
sarat,

8
Se hai appena cambiato git ignore e hai aggiunto git - tutti per includere molti file, NON eseguire git reset --hard per annullare la messa in scena. SARANNO ELIMINATI !!
Goditi

5
Uwaaahh !! Forse devi evidenziare la parola "con attenzione" . Ho appena visto queste tre parole "git reset --hard" e tutti i miei file non messi in scena sono ... fufff !! andato!!!!!
Vineeth Chitteti,

1

Se desideri annullare la messa in scena di tutte le modifiche, usa il comando seguente,

git reset --soft HEAD

Nel caso in cui desideri annullare la modifica delle modifiche e ripristinarle dalla directory di lavoro,

git reset --hard HEAD
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.