version-control reset - Come annullare 'git add' prima di eseguire il commit?




checkout file (25)

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 su git qui sono "r" (ripristina), "1" (la prima voce nella lista ripristina gli spettacoli), "ritorna" per uscire dalla 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, dimostrando 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)
$

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.


Correre

git gui

e rimuovere tutti i file manualmente o selezionandoli tutti e facendo clic sul pulsante non rilascia dal pulsante di commit .


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.

Git file di gestione temporanea


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

git reset HEAD myfile.txt

Spiegare:

Dopo aver messo in scena i file indesiderati, per annullare, puoi eseguire il 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 accadere in questi casi:


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 fare il 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 in seguito 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, usando le tue attuali impostazioni di fine riga.

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

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

in caso di dubbio, utilizzare

git reset HEAD file

Perché fa la cosa prevista in entrambi i casi.

Attenzione: se si esegue git rm --cached file su un file che è stato modificato (un file preesistente nel repository), il file verrà rimosso su git commit ! Esisterà ancora nel tuo file system, ma se qualcun altro prende il tuo commit, il file verrà cancellato 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

git add myfile.txt # per aggiungere 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, lo ripristinerà semplicemente


git reset filename.txt  

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


Questo comando annulla le modifiche:

git reset HEAD filename.txt

Puoi anche usare

git add -p 

aggiungere parti di file.


Per chiarire: git add sposta le modifiche dalla directory di lavoro corrente all'area di staging (indice).

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

git stage

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

Peccato che non ci sia git unstage né comandi git 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

Se si digita:

git status

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

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)

usa il comando * per gestire più file alla volta

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

eccetera


In SourceTree puoi farlo facilmente tramite la GUI. Puoi 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:

Unstaging files [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 resetper rimuovere i nuovi file.


Un'aggiunta alla risposta accettata, se il file aggiunto erroneamente era 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 chiarire una certa 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 - in sicurezza, in generale.

Ricordiamo innanzitutto cosa git add <file> realtà:

  1. Se <file> non è stato tracciato in precedenza , git add aggiunge alla cache , con il suo contenuto corrente.

  2. Se <file> è già stato tracciato , git add salva il contenuto corrente (istantanea, versione) nella cache. In GIT, questa azione è ancora chiamata add , (non è un semplice aggiornamento ), perché due diverse versioni (istantanee) di un file sono considerate due elementi diversi: quindi, stiamo effettivamente aggiungendo un nuovo elemento alla cache, per essere infine impegnato 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 "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: essere consapevoli del fatto che git reset HEAD non può recuperare magicamente il contenuto del file precedentemente memorizzato, lo risincronizza semplicemente dall'HEAD. Se il nostro git add fuorviato ha sovrascritto una versione precedente non salvata, non possiamo recuperarla. 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

Ovviamente, 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 poi sovrascritte - vedi i commenti di Johannes Matokic e iolsmit)


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 precedenti sono equivalenti a git reset HEAD <file> e git reset HEAD rispettivamente, e falliranno se HEAD è indefinito (perché non hai ancora fatto alcun commit nel tuo repository) o ambiguo (perché tu creato un ramo chiamato HEAD , che è una cosa stupida che non dovresti fare). Questo è stato cambiato in Git 1.8.2 , 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).


git rm --cached . -r

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


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.


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 usato git add . oppure 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>
    
  • Ripristina 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 funzionerà 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>
    

Per annullare git aggiungi uso

git reset filename


Digita semplicemente git reset che tornerà indietro ed è come se non avessi mai digitato git add . dal tuo ultimo impegno. Assicurati di aver commesso prima.


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

git help rm

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)


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 i dettagli o ..

Semplicemente,

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

Ora puoi

git unadd foo.txt bar.txt

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

git reset *

Trova l'ultimo commit che ha interessato il percorso specificato. Poiché il file non è nel commit HEAD, questo commit deve averlo eliminato.

git rev-list -n 1 HEAD -- <file_path>

Quindi verifica la versione al commit prima, usando il simbolo caret ( ^ ):

git checkout <deleting_commit>^ -- <file_path>

O in un comando, se $file è il file in questione.

git checkout $(git rev-list -n 1 HEAD -- "$file")^ -- "$file"

Se stai usando zsh e hai abilitato l'opzione EXTENDED_GLOB, il simbolo del punto di inserimento non funzionerà. Puoi usare ~1 invece.

git checkout $(git rev-list -n 1 HEAD -- "$file")~1 -- "$file"




git version-control git-commit git-stage