Além da resposta aceita, se o arquivo adicionado por engano for enorme, você provavelmente perceberá que, mesmo depois de removê-lo do índice com ' git reset
', ele ainda parece ocupar espaço no .git
diretório.
Isso não é nada para se preocupar; o arquivo ainda está no repositório, mas apenas como um "objeto solto". Ele não será copiado para outros repositórios (via clone, push) e o espaço será recuperado eventualmente - embora talvez não em breve. Se você estiver ansioso, você pode executar:
git gc --prune=now
Atualização (a seguir, é minha tentativa de esclarecer algumas confusões que podem surgir das respostas mais votadas):
Então, qual é o verdadeiro desfazer de git add
?
git reset HEAD <file>
?
ou
git rm --cached <file>
?
A rigor, e se não me engano: nenhum .
git add
não pode ser desfeito - com segurança, em geral.
Vamos lembrar primeiro o que git add <file>
realmente faz:
Se não<file>
foi rastreado anteriormente , o git add
adiciona ao cache , com seu conteúdo atual.
Se já<file>
foi rastreado , git add
salva o conteúdo atual (instantâneo, versão) no cache. No Git, essa ação ainda é chamada de adição (não apenas uma atualização ), porque duas versões diferentes (instantâneos) de um arquivo são consideradas como dois itens diferentes: portanto, estamos realmente adicionando um novo item ao cache, para ser eventualmente cometido mais tarde.
À luz disso, a questão é um pouco ambígua:
Por engano, adicionei arquivos usando o comando ...
O cenário do OP parece ser o primeiro (arquivo não rastreado), queremos que o "desfazer" remova o arquivo (não apenas o conteúdo atual) dos itens rastreados. Se for esse o caso, não há problema em executar git rm --cached <file>
.
E também poderíamos correr git reset HEAD <file>
. Geralmente, isso é preferível, porque funciona nos dois cenários: ele também desfaz quando adicionamos erroneamente uma versão de um item já rastreado.
Mas existem duas advertências.
Primeiro: existe (como indicado na resposta) apenas um cenário em que git reset HEAD
não funciona, mas git rm --cached
funciona: um novo repositório (sem confirmação). Mas, realmente, este é um caso praticamente irrelevante.
Segundo: esteja ciente de que git reset HEAD
não é possível recuperar magicamente o conteúdo do arquivo em cache anteriormente, apenas o ressincroniza a partir do HEAD. Se nossos git add
erros de orientação substituíram uma versão não confirmada em etapas anterior, não podemos recuperá-la. É por isso que, estritamente falando, não podemos desfazer [*].
Exemplo:
$ 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
Obviamente, isso não é muito crítico se apenas seguirmos o fluxo de trabalho preguiçoso usual de fazer 'git add' apenas para adicionar novos arquivos (caso 1) e atualizarmos novos conteúdos por meio do git commit -a
comando commit,
* (Editar: o acima exposto está praticamente correto, mas ainda pode haver algumas maneiras levianas / complicadas de recuperar as mudanças que foram encenadas, mas não confirmadas e depois substituídas - veja os comentários de Johannes Matokic e iolsmit)
HEAD
ouhead
agora pode usar@
no lugar deHEAD
vez. Veja esta resposta (última seção) para saber por que você pode fazer isso.