it-swarm.it

Come annullare 'git add' prima di eseguire il commit?

Ho erroneamente aggiunto file a git usando il comando:

git add myfile.txt

Non ho ancora eseguito git commit. C'è un modo per annullare questo, quindi questi file non saranno inclusi nel commit?


Ci sono finora 48 risposte (alcune cancellate). Si prega di non aggiungerne uno nuovo se non si hanno nuove informazioni.

8101
paxos1977

Puoi annullare git add prima di eseguire il commit

git reset <file>

che lo rimuoverà dall'indice corrente (l'elenco "in procinto di essere impegnato") senza cambiare altro.

Puoi usare

git reset

senza alcun nome di file per rimuovere tutte le modifiche dovute. Questo può tornare utile quando ci sono troppi file da elencare uno per uno in un ragionevole lasso di tempo.

Nelle vecchie versioni di Git, i comandi sopra sono equivalenti a git reset HEAD <file> e git reset HEAD rispettivamente, e falliranno se HEAD non è definito (perché non hai ancora fatto alcun commit nel repository) o ambiguo (perché hai creato un ramo chiamato HEAD, che è una cosa stupida che non dovresti fare). Questo è stato modificato in Git 1.8.2 , tuttavia, quindi nelle versioni moderne di Git puoi usare i comandi precedenti anche prima di fare il tuo primo commit:

"git reset" (senza opzioni o parametri) utilizzato per l'errore quando non si ha alcun commit nella cronologia, ma ora fornisce un indice vuoto (per abbinare il commit inesistente su cui non si è nemmeno attivi).

9181
genehack

Tu vuoi:

git rm --cached <added_file_to_undo>

Ragionamento:

Quando ero nuovo a questo, ho provato per la prima volta

git reset .

(per annullare l'intera aggiunta iniziale), solo per ottenere questo (non così) messaggio utile:

fatal: Failed to resolve 'HEAD' as a valid ref.

Si scopre che questo è dovuto al fatto che HEAD ref (branch?) Non esiste fino a dopo il primo commit. Cioè, ti imbatterai nello stesso problema del principiante come me se il tuo flusso di lavoro, come il mio, fosse qualcosa del tipo:

  1. cd alla mia grande nuova directory di progetto per provare Git, il nuovo hotness
  2. git init
  3. git add .
  4. git status

    ... un sacco di pergamene per ...

    => Accidenti, non volevo aggiungere tutto questo.

  5. google "annulla git add"

    => trova Stack Overflow - yay

  6. git reset .

    => fatale: impossibile risolvere 'HEAD' come riferimento valido.

Risulta inoltre che c'è un bug registrato contro l'inutilità di questo nella mailing list.

E che la soluzione corretta era proprio lì nell'output di stato Git (che, sì, ho sorvolato come "schifo")

...
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
...

E la soluzione è davvero usare git rm --cached FILE.

Nota gli avvertimenti qui altrove - git rm cancella la tua copia di lavoro locale del file, ma not se usi --cached . Ecco il risultato di git help rm:

--cached Utilizzare questa opzione per rimuovere e rimuovere i percorsi solo dall'indice. I file dell'albero di lavoro, modificati o meno, saranno lasciati.

Procedo ad usare

git rm --cached .

rimuovere tutto e ricominciare. Non ha funzionato però, perché mentre add . è ricorsivo, risulta che rm richiede -r per recurse. Sospiro.

git rm -r --cached .

Ok, ora sono tornato a dove ho iniziato. La prossima volta userò -n per fare una prova a secco e vedere cosa verrà aggiunto:

git add -n .

Ho chiuso tutto in un posto sicuro prima di fidarmi di git help rm sul --cached non distruggendo nulla (e se l'avessi scritto male).

2047
Rhubarb

Se si digita:

git status

git ti dirà cosa è messo in scena, ecc., incluse le istruzioni su come non rilasciare:

use "git reset HEAD <file>..." to unstage

Trovo che git faccia un buon lavoro a spingermi a fare la cosa giusta in situazioni come questa.

Nota: le versioni git recenti (1.8.4.x) hanno cambiato questo messaggio:

(use "git rm --cached <file>..." to unstage)
507
Paul Beckingham

Per chiarire: git add sposta le modifiche dalla directory di lavoro corrente alla area di staging (index).

Questo processo è chiamato staging . Quindi il comando più naturale per stage le modifiche (file modificati) è ovvio:

git stage

git add è solo un più facile da digitare alias per git stage

Peccato che non ci siano comandi git unstagegit unadd. Quello pertinente è più difficile da indovinare o ricordare, ma è piuttosto ovvio:

git reset HEAD --

Possiamo facilmente creare un alias per questo:

git config --global alias.unadd 'reset HEAD --'
git config --global alias.unstage 'reset HEAD --'

E infine, abbiamo nuovi comandi:

git add file1
git stage file2
git unadd file2
git unstage file1

Personalmente uso anche alias più brevi:

git a #for staging
git u #for unstaging
238
takeshin

Un'aggiunta alla risposta accettata, se il file aggiunto erroneamente fosse enorme, probabilmente noterete che, anche dopo averlo rimosso dall'indice con 'git reset', sembra ancora occupare spazio nella directory .git. Questo non è nulla di cui preoccuparsi, il file è effettivamente ancora nel repository, ma solo come "oggetto libero", non verrà copiato in altri repository (tramite clone, Push) e lo spazio verrà infine recuperato - sebbene forse non molto presto. Se sei ansioso, puoi eseguire:

git gc --Prune=now

Aggiornamento (ciò che segue è il mio tentativo di eliminare una certa confusione che può derivare dalle risposte più votate):

Quindi, qual è il vero undo di git add?

git reset HEAD <file>?

o

git rm --cached <file>?

A rigor di termini, e se non sbaglio: none .

git add non può essere annullato - in modo sicuro, in generale.

Ricordiamo innanzitutto cosa fa git add <file>:

  1. Se <file> era non precedentemente tracciato , git add lo aggiunge alla cache , con il suo contenuto corrente.

  2. Se <file> era già tracciato , git add salva il contenuto corrente (snapshot, versione) nella cache. In GIT, questa azione è ancora chiamata add , (non mere update it), perché due diverse versioni (istantanee) di un file sono considerate due elementi diversi: quindi, stiamo davvero aggiungendo un nuovo elemento nella cache, per essere eventualmente impegnato in seguito.

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 "undo" rimuova il file (non solo il contenuto corrente) dagli elementi tracciati. Se questo è il caso, allora è ok per eseguire git rm --cached <file>.

E potremmo anche eseguire git reset HEAD <file>. Questo è generalmente preferibile, perché funziona in entrambi gli scenari: fa anche l'annullamento quando abbiamo aggiunto erroneamente una versione di un oggetto già tracciato.

Ma ci sono due avvertimenti.

Primo: C'è (come sottolineato nella risposta) solo uno scenario in cui git reset HEAD non funziona, ma git rm --cached fa: un nuovo repository (nessun commit). Ma, davvero, questo è un caso praticamente irrilevante.

Secondo: tieni presente che git reset HEAD non può recuperare magicamente il contenuto del file precedentemente memorizzato, ma lo risincronizza dall'HEAD. Se il nostro git add errato ha sovrascritto una versione precedente non implementata, non possiamo ripristinarla. Ecco perché, in senso stretto, 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 lost irrevocably "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 comando commit, git commit -a.


* (Modifica: quanto sopra è praticamente corretto, ma ci possono essere alcuni modi un po 'hacker/complicati per recuperare le modifiche che sono state messe in scena ma non impegnate e quindi sovrascritte - vedi i commenti di Johannes Matokic e iolsmit)

161
leonbloy
git rm --cached . -r

"annulla" tutto ciò che hai aggiunto dalla tua directory corrente in modo ricorsivo

91
braitsch

Correre

git gui

e rimuovere tutti i file manualmente o selezionandoli tutti e facendo clic su nonstage da commit button.

85

Undo un file che è già stato aggiunto è abbastanza semplice usando git , per resettare myfile.txt che già aggiunto, usa:

git reset HEAD myfile.txt

Spiega:

Dopo aver messo in scena file indesiderati, per annullare, puoi fare git reset, Head è la testa del tuo file in locale e l'ultimo parametro è il nome del tuo file.

Creo i passaggi nell'immagine sottostante in ulteriori dettagli per te, compresi tutti i passaggi che possono verificarsi in questi casi:

 git reset HEAD file

82
Alireza

Git ha comandi per ogni azione immaginabile, ma ha bisogno di una conoscenza approfondita per fare le cose per bene e per questo è al massimo intuitivo ...

Cosa hai fatto prima:

  • Modificato un file e utilizzato git add . o git add <file>.

Ciò che vuoi:

  • Rimuovi il file dall'indice, ma mantienilo aggiornato e lasciato con modifiche non vincolate nella copia di lavoro:

    git reset head <file>
    
  • Reimposta il file all'ultimo stato da HEAD, annullando le modifiche e rimuovendole dall'indice:

    # Think `svn revert <file>` IIRC.
    git reset HEAD <file>
    git checkout <file>
    
    # If you have a `<branch>` named like `<file>`, use:
    git checkout -- <file>
    

    Questo è necessario poiché git reset --hard HEAD non funziona con singoli file.

  • Rimuovi <file> dall'indice e dal controllo delle versioni, mantenendo il file non versione con le modifiche nella copia di lavoro:

    git rm --cached <file>
    
  • Rimuovi <file> dalla copia di lavoro e dal controllo delle versioni completamente:

    git rm <file>
    
80
sjas

La domanda non è chiaramente posta. Il motivo è che git add ha due significati:

  1. aggiungendo un nuovo file all'area di staging, quindi annulla con git rm --cached file.
  2. aggiungendo un modificato file all'area di staging, quindi annulla con git reset HEAD file.

in caso di dubbio, usare

git reset HEAD file

Perché fa la cosa prevista in entrambi i casi.

Attenzione: se fai git rm --cached file su un file che era modificato (un file che esisteva prima nel repository), allora il file verrà rimosso su git commit! Esisterà ancora nel tuo file system, ma se qualcun altro prende il tuo commit, il file verrà eliminato dalla loro struttura di lavoro.

git status ti dirà se il file era un nuovo file o modificato :

On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   my_new_file.txt
    modified:   my_modified_file.txt
71
Michael_Scharf

Se sei sul tuo commit iniziale e non puoi usare git reset, basta dichiarare "Git bankruptcy" ed eliminare la cartella .git e ricominciare

61
Paul Betts

Come per molte altre risposte puoi usare git reset

MA:

Ho trovato questo piccolo post che aggiunge effettivamente il comando Git (beh un alias) per git unadd: vedi git unadd per dettagli o ..

Semplicemente,

git config --global alias.unadd "reset HEAD"

Ora puoi

git unadd foo.txt bar.txt
55
electblake

git remove o git rm possono essere utilizzati per questo, con il flag --cached. Provare:

git help rm
46
gnud

Usa git add -i per rimuovere i file appena aggiunti dal tuo imminente commit. Esempio:

Aggiungere il file che non volevi:

$ git add foo
$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       new file:   foo
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
# [...]#

Entrando in interattivo aggiungi per annullare il tuo add (i comandi digitati a git qui sono "r" (ripristina), "1" (la prima voce nella lista ripristina gli spettacoli), "ritorna" per abbandonare la modalità di ripristino e "q" (smettere):

$ git add -i
           staged     unstaged path
  1:        +1/-0      nothing foo

*** Commands ***
  1: [s]tatus     2: [u]pdate     3: [r]evert     4: [a]dd untracked
  5: [p]atch      6: [d]iff       7: [q]uit       8: [h]elp
What now> r
           staged     unstaged path
  1:        +1/-0      nothing [f]oo
Revert>> 1
           staged     unstaged path
* 1:        +1/-0      nothing [f]oo
Revert>> 
note: foo is untracked now.
reverted one path

*** Commands ***
  1: [s]tatus     2: [u]pdate     3: [r]evert     4: [a]dd untracked
  5: [p]atch      6: [d]iff       7: [q]uit       8: [h]elp
What now> q
Bye.
$

Questo è tutto! Ecco la tua dimostrazione, mostrando che "pippo" è tornato nella lista non tracciata:

$ git status
# On branch master
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
# [...]
#       foo
nothing added to commit but untracked files present (use "git add" to track)
$
42
Alex North-Keys

Ecco un modo per evitare questo problema irritante quando si avvia un nuovo progetto:

  • Crea la directory principale per il tuo nuovo progetto.
  • Esegui git init.
  • Ora crea un file .gitignore (anche se è vuoto).
  • Configura il tuo file .gitignore.

Git rende davvero difficile git reset se non si hanno commit. Se crei un piccolo commit iniziale solo per il gusto di averne uno, dopo puoi git add -A e git reset tutte le volte che vuoi per avere tutto a posto.

Un altro vantaggio di questo metodo è che se ci si imbatte in problemi di fine riga e si ha bisogno di aggiornare tutti i file, è facile:

  • Controlla quel commit iniziale. Questo rimuoverà tutti i tuoi file.
  • Quindi controlla di nuovo il commit più recente. Ciò recupererà nuove copie dei tuoi file, utilizzando le impostazioni di fine riga correnti.
37
Ryan Lundy

Forse Git si è evoluto da quando hai postato la tua domanda.

$> git --version
git version 1.6.2.1

Ora puoi provare:

git reset HEAD .

Questo dovrebbe essere quello che stai cercando.

33
Kokotte23

Si noti che se non si specifica una revisione, è necessario includere un separatore. Esempio dalla mia console:

git reset <path_to_file>
fatal: ambiguous argument '<path_to_file>': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions

git reset -- <path_to_file>
Unstaged changes after reset:
M   <path_to_file>

(versione git 1.7.5.4)

33
powlo

Per rimuovere nuovi file dall'area di gestione temporanea (e solo in caso di un nuovo file), come suggerito sopra:

git rm --cached FILE

Usa rm --cached solo per i nuovi file aggiunti per sbaglio.

30
Ran

Per ripristinare tutti i file in una particolare cartella (e le relative sottocartelle), puoi usare il seguente comando:

git reset *
24
Zorayr

usa il comando * per gestire più file alla volta

git reset HEAD *.prj
git reset HEAD *.bmp
git reset HEAD *gdb*

eccetera

24
boulder_ruby

Basta digitare git reset per tornare indietro ed è come se non avessi mai digitato git add . dal tuo ultimo commit. Assicurati di aver commesso prima.

22
Donovan

Supponiamo che crei un nuovo file newFile.txt.

 enter image description here

Supponiamo che aggiungo il file accidentalmente, git add newFile.txt

 enter image description here

Ora voglio annullare questo add, prima di commit, git reset newFile.txt

 enter image description here

18
Vidura Mudalige

Per un file specifico:

  • git resetta my_file.txt
  • git checkout my_file.txt

Per tutti i file aggiunti:

  • git reset.
  • git checkout.

Nota: checkout cambia il codice nei file e passa all'ultimo stato (commit) aggiornato. reset non modifica i codici; semplicemente resetta l'intestazione.

17
Hasib Kamal

Per annullare git aggiungi uso

git reset filename

13
Anirudh Sood

Questo comando annulla le modifiche:

git reset HEAD filename.txt

Puoi anche usare

git add -p 

aggiungere parti di file.

13
wallerjake

Sono sorpreso che nessuno menzioni la modalità interattiva:

git add -i

scegli l'opzione 3 per aggiungere i file. Nel mio caso, spesso desidero aggiungere più di un file, con la modalità interattiva è possibile utilizzare numeri come questo per aggiungere file. Questo prenderà tutto tranne 4: 1,2,3,5

Per scegliere una sequenza basta digitare 1-5 per prendere tutto da 1 a 5.

File di gestione temporanea Git

13
Jonathan

git add myfile.txt # questo aggiungerà il tuo file alla lista dei commit

Al contrario di questo comando,

git reset HEAD myfile.txt  # this will undo it. 

così, sarai nello stato precedente. specificato sarà nuovamente nell'elenco non tracciato (stato precedente).

resetterà la tua testa con quel file specificato. quindi, se la tua testa non ce l'ha significa, la reimposterà semplicemente

9
Silent Spectator
git reset filename.txt

Rimuoverà un file denominato nomefile.txt dall'indice corrente, l'area "in procinto di essere impegnata", senza cambiare altro.

9
Rahul Sinha

In SourceTree puoi farlo facilmente tramite la GUI. È possibile controllare quale comando usa sourcetree per rimuovere un file.

Ho creato un nuovo file e l'ho aggiunto a git. Poi l'ho staccato usando la GUI di SourceTree. Questo è il risultato:

File non archiviati [08/12/15 10:43]
git -c diff.mnemonicprefix = false -c core.quotepath = false -c credential.helper = sourcetree reset -q - percorso/su/file/nomefile.Java

SourceTree utilizza reset per rimuovere i nuovi file.

8
miva2
git reset filename.txt  

Rimuoverà un file denominato nomefile.txt dall'indice corrente, l'area "in procinto di essere impegnata", senza cambiare altro.

7
Joseph Mathew

Una delle soluzioni più intuitive sta usando SourceTree .

Puoi semplicemente trascinare e rilasciare i file da staging e nonstaged  enter image description here

7
Marcin Szymczak

Il comando git reset ti aiuta a modificare l'area di staging o l'area di staging e l'albero di lavoro. La capacità di Git di creare commit si comporta esattamente come vuoi, significa che a volte devi annullare le modifiche alle modifiche che hai organizzato con git add.

Puoi farlo chiamando git reset HEAD <file to change>. Hai due opzioni per eliminare completamente le modifiche. git checkout HEAD <file(s) or path(s)> è un modo rapido per annullare le modifiche all'area di staging e alla struttura di lavoro. Fai attenzione con questo comando, tuttavia, perché rimuove tutte le modifiche al tuo albero di lavoro. Git non conosce tali cambiamenti poiché non sono mai stati commessi. Non è possibile ripristinare tali modifiche dopo aver eseguito questo comando.

Un altro comando a tua disposizione è git reset --hard. È ugualmente distruttivo per il tuo albero di lavoro: qualsiasi modifica non vincolante o modifiche graduali vengono perse dopo l'esecuzione. L'esecuzione di git reset -hard HEAD fa la stessa cosa di git checkout HEAD. Semplicemente non richiede un file o un percorso per funzionare.

Puoi usare --soft con git reset. Reimposta il repository sul commit specificato e ne mette in scena tutte le modifiche. Le modifiche che hai già messo in scena non sono influenzate, né i cambiamenti nella tua struttura di lavoro.

Infine, è possibile utilizzare --mixed per reimpostare l'albero di lavoro senza apportare modifiche. Ciò disimpegna anche le eventuali modifiche apportate.

1
SAIguru011