Un'aggiunta alla risposta accettata, se il tuo file aggiunto per errore era enorme, probabilmente noterai che, anche dopo averlo rimosso dall'indice con ' git reset
', sembra ancora occupare spazio nella .git
directory.
Questo non è nulla di cui preoccuparsi; il file è effettivamente ancora nel repository, ma solo come "oggetto sciolto". Non verrà copiato in altri repository (tramite clone, push) e lo spazio verrà infine recuperato, anche se forse non molto presto. Se sei ansioso, puoi eseguire:
git gc --prune=now
Aggiornamento (quello che segue è il mio tentativo di eliminare un po 'di confusione che può derivare dalle risposte più votate):
Quindi, qual è il vero annullamento di git add
?
git reset HEAD <file>
?
o
git rm --cached <file>
?
A rigor di termini, e se non sbaglio: nessuno .
git add
non può essere annullato - sicuro, in generale.
Ricordiamo innanzitutto cosa git add <file>
fa effettivamente:
Se non<file>
è stato precedentemente monitorato , lo git add
aggiunge alla cache , con il suo contenuto corrente.
Se <file>
è già stato monitorato , git add
salva il contenuto corrente (istantanea, versione) nella cache. In Git, questa azione è ancora chiamata add , (non semplice aggiornamento ), perché due diverse versioni (istantanee) di un file sono considerate come due elementi diversi: quindi, stiamo davvero aggiungendo un nuovo elemento nella cache, per essere infine commesso più tardi.
Alla luce di ciò, la domanda è leggermente ambigua:
Ho erroneamente aggiunto file usando il comando ...
Lo scenario dell'OP sembra essere il primo (file non tracciato), vogliamo che "annulla" rimuova il file (non solo il contenuto corrente) dagli elementi tracciati. Se questo è il caso, allora è ok per l'esecuzione git rm --cached <file>
.
E potremmo anche correre git reset HEAD <file>
. Questo è generalmente preferibile, perché funziona in entrambi gli scenari: fa anche l'annullamento quando abbiamo erroneamente aggiunto una versione di un elemento già tracciato.
Ma ci sono due avvertimenti.
Primo: esiste (come sottolineato nella risposta) un solo scenario in cui git reset HEAD
non funziona, ma git rm --cached
funziona: un nuovo repository (nessun commit). Ma, davvero, questo è un caso praticamente irrilevante.
Secondo: tenere presente che git reset HEAD
non è possibile ripristinare magicamente il contenuto del file precedentemente memorizzato nella cache, ma lo risincronizza da HEAD. Se la nostra guida errata ha git add
sovrascritto una versione non messa in scena precedente, non possiamo recuperarla. Ecco perché, a rigore, non possiamo annullare [*].
Esempio:
$ git init
$ echo "version 1" > file.txt
$ git add file.txt # First add of file.txt
$ git commit -m 'first commit'
$ echo "version 2" > file.txt
$ git add file.txt # Stage (don't commit) "version 2" of file.txt
$ git diff --cached file.txt
-version 1
+version 2
$ echo "version 3" > file.txt
$ git diff file.txt
-version 2
+version 3
$ git add file.txt # Oops we didn't mean this
$ git reset HEAD file.txt # Undo?
$ git diff --cached file.txt # No dif, of course. stage == HEAD
$ git diff file.txt # We have irrevocably lost "version 2"
-version 1
+version 3
Naturalmente, questo non è molto critico se seguiamo il solito flusso di lavoro pigro di fare 'git add' solo per aggiungere nuovi file (caso 1) e aggiorniamo nuovi contenuti tramite il git commit -a
comando commit .
* (Modifica: quanto sopra è praticamente corretto, ma possono esserci ancora alcuni modi leggermente hacker / contorti per recuperare le modifiche messe in scena, ma non impegnate e poi sovrascritte - vedi i commenti di Johannes Matokic e iolsmit)
HEAD
ohead
possono ora utilizzare@
al posto diHEAD
. Vedi questa risposta (ultima sezione) per sapere perché puoi farlo.