ti-enxame.com

Como desfazer 'git add' antes de confirmar?

Eu, por engano, adicionei arquivos ao git usando o comando:

git add myfile.txt

Ainda não corri o git commit. Existe uma maneira de desfazer isso, então esses arquivos não serão incluídos no commit?


Existem 48 respostas até agora (algumas excluídas). Por favor, não adicione um novo a menos que você tenha alguma informação nova.

8101
paxos1977

Você pode desfazer git add antes de confirmar

git reset <file>

que irá removê-lo do índice atual (a lista "prestes a ser confirmada") sem alterar nada.

Você pode usar

git reset

sem nenhum nome de arquivo para desassociar todas as alterações devidas. Isso pode ser útil quando houver muitos arquivos a serem listados, um por um, em um período de tempo razoável.

Em versões antigas do Git, os comandos acima são equivalentes a git reset HEAD <file> e git reset HEAD respectivamente, e falharão se HEAD for indefinido (porque você ainda não fez nenhum commit no seu repo) ou ambíguo (porque você criou um branch chamado HEAD, que é uma coisa estúpida que você não deveria fazer). Este foi alterado no Git 1.8.2 , no entanto, nas versões modernas do Git você pode usar os comandos acima mesmo antes de fazer seu primeiro commit:

"git reset" (sem opções ou parâmetros) usado para errar quando você não tem nenhum commit no seu histórico, mas agora ele fornece um índice vazio (para corresponder ao commit inexistente que você nem está usando).

9181
genehack

Você quer:

git rm --cached <added_file_to_undo>

Raciocínio:

Quando eu era novo nisso, eu tentei pela primeira vez

git reset .

(para desfazer todo o meu add inicial), apenas para obter essa (não tão) mensagem útil:

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

Acontece que isso acontece porque o HEAD ref (branch?) Não existe até depois do primeiro commit. Ou seja, você terá o mesmo problema de iniciante que eu se o seu fluxo de trabalho, como o meu, for algo como:

  1. cd para o meu novo diretório de projetos para testar o Git, o novo hotness
  2. git init
  3. git add .
  4. git status

    ... muitos rolos de porcaria por ...

    => Porra, eu não queria adicionar tudo isso.

  5. google "desfazer git add"

    => encontrar estouro de pilha - yay

  6. git reset .

    => fatal: falha ao resolver "CABEÇA" como referência válida.

Acontece que há um bug registrado contra a falta de utilidade disso na lista de discussão.

E que a solução correta estava lá na saída de status do Git (que, sim, eu encarei como "porcaria")

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

E a solução, na verdade, é usar git rm --cached FILE.

Observe os avisos em outro lugar aqui - git rm exclui sua cópia de trabalho local do arquivo, mas not se você usar --cached . Aqui está o resultado de git help rm:

--cached Use esta opção para desassociar e remover caminhos apenas do índice. Os arquivos da árvore de trabalho, modificados ou não, serão deixados.

Eu continuo a usar

git rm --cached .

para remover tudo e começar de novo. Não funcionou, porque enquanto o add . é recursivo, o rm precisa de -r para ser recursivo. Suspiro.

git rm -r --cached .

Ok, agora estou de volta para onde comecei. Da próxima vez vou usar -n para fazer uma corrida seca e ver o que será adicionado:

git add -n .

Fechei tudo em um local seguro antes de confiar em git help rm sobre o --cached não destruir nada (e se eu escrevê-lo incorretamente).

2047
Rhubarb

Se você digitar:

git status

o git lhe dirá o que é encenado, etc, incluindo instruções sobre como desassociar:

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

Eu acho que o git faz um bom trabalho me cutucando para fazer a coisa certa em situações como essa.

Nota: versões git recentes (1.8.4.x) mudaram esta mensagem:

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

Para esclarecer: git add move as alterações do diretório de trabalho atual para a área de preparação(index).

Este processo é chamado temporário . Portanto, o comando mais natural para o stage as mudanças (arquivos alterados) é o óbvio:

git stage

git add é apenas mais fácil de digitar alias para git stage

Pena que não há comandos git unstage nem git unadd. O mais relevante é mais difícil de adivinhar ou lembrar, mas é bastante óbvio:

git reset HEAD --

Podemos facilmente criar um alias para isso:

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

E finalmente, temos novos comandos:

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

Pessoalmente eu uso aliases ainda mais curtos:

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

Uma adição à resposta aceita, se o seu arquivo adicionado por engano foi enorme, você provavelmente notará que, mesmo depois de removê-lo do índice com 'git reset', ele ainda parece ocupar espaço no diretório .git. 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á eventualmente recuperado - embora talvez não muito em breve. Se você está ansioso, você pode correr:

git gc --Prune=now

Update (o que segue é minha tentativa de esclarecer alguma confusão que pode surgir das respostas mais votadas):

Então, qual é o real undo de git add?

git reset HEAD <file>?

ou

git rm --cached <file>?

Estritamente falando, e se não me engano: none .

git add não pode ser desfeito - com segurança, em geral.

Vamos nos lembrar primeiro do que git add <file> realmente faz:

  1. Se <file> for não foi rastreado anteriormente , git add adiciona-o ao cache , com seu conteúdo atual.

  2. Se <file> for já rastreado , git add salva o conteúdo atual (snapshot, versão) no cache. No GIT, essa ação ainda é chamada add , (não é mera update it), porque duas versões diferentes (snapshots) de um arquivo são consideradas como dois itens diferentes: portanto, estamos de fato adicionando um novo item para o cache, para ser posteriormente confirmado posteriormente.

Em vista disso, a questão é um pouco ambígua:

Eu, 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 este for o caso, então está ok rodar git rm --cached <file>.

E também podemos executar git reset HEAD <file>. Em geral, isso é preferível, porque funciona em ambos os cenários: ele também desfaz quando adicionamos erroneamente uma versão de um item já rastreado.

Mas existem duas ressalvas.

Primeiro: Existe (como apontado na resposta) apenas um cenário em que git reset HEAD não funciona, mas git rm --cached faz: um novo repositório (sem commits). Mas, na verdade, este é um caso praticamente irrelevante.

Segundo: Esteja ciente de que git reset HEAD não pode recuperar magicamente o conteúdo do arquivo armazenado em cache, apenas o ressincroniza a partir do HEAD. Se nosso git add desorientado tiver sobrescrito uma versão anterior não consolidada, não poderemos 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 lost irrevocably "version 2"
-version 1
+version 3

Claro, 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 (case 1), e nós atualizarmos novos conteúdos via commit, o comando git commit -a.


* (Edit: o acima é praticamente correto, mas ainda pode haver algumas maneiras ligeiramente hackish/convoluted para recuperar as alterações que foram encenadas, mas não confirmadas e, em seguida, substituídas - ver os comentários por Johannes Matokic e iolsmit)

161
leonbloy
git rm --cached . -r

irá "un-adicionar" tudo o que você adicionou a partir do seu diretório atual recursivamente

91
braitsch

Corre

git gui

e remova todos os arquivos manualmente ou selecionando todos eles e clicando no botão unstage from commit .

85
Khaja Minhajuddin

Desfazer um arquivo que já foi adicionado é bastante fácil usando git , para resetar myfile.txt que já adicionado, use:

git reset HEAD myfile.txt

Explique:

Depois que você colocou o (s) arquivo (s) indesejado (s), para desfazer, você pode fazer git reset, Head é a cabeça do seu arquivo em local e o último parâmetro é o nome do seu arquivo.

Eu crio as etapas na imagem abaixo com mais detalhes para você, incluindo todas as etapas que podem acontecer nesses casos:

git reset HEAD file

82
Alireza

O Git tem comandos para cada ação imaginável, mas precisa de extenso conhecimento para acertar as coisas e, por isso, é contra-intuitivo na melhor das hipóteses ...

O que você fez antes:

  • Alterou um arquivo e usou git add . ou git add <file>.

O que você quer:

  • Remova o arquivo do índice, mas mantenha-o com as versões e mantenha as alterações não confirmadas na cópia de trabalho:

    git reset head <file>
    
  • Redefina o arquivo para o último estado de HEAD, desfazendo as alterações e removendo-as do índice:

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

    Isso é necessário porque git reset --hard HEAD não funcionará com arquivos únicos.

  • Remova <file> do índice e do controle de versão, mantendo o arquivo não versionado com alterações na cópia de trabalho:

    git rm --cached <file>
    
  • Remova <file> da cópia de trabalho e do versionamento completamente:

    git rm <file>
    
80
sjas

A questão não é claramente colocada. A razão é que git add tem dois significados:

  1. adicionando um novo arquivo para a área temporária, então desfaça com git rm --cached file.
  2. adicionando um arquivo modified na área de preparação, então desfaça com git reset HEAD file.

em caso de dúvida, use

git reset HEAD file

Porque faz o esperado em ambos os casos.

Atenção: se você fizer git rm --cached file em um arquivo que foi modified (um arquivo que existia antes no repositório), então o arquivo será removido em git commit! Ele ainda existirá no seu sistema de arquivos, mas se alguém mais enviar sua confirmação, o arquivo será excluído da árvore de trabalho.

git status dir-lhe-á se o ficheiro era um novo ficheiro ou modificado :

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 você está no seu commit inicial e não pode usar git reset, apenas declare "Git bankruptcy" e delete a pasta .git e comece novamente.

61
Paul Betts

De acordo com muitas outras respostas, você pode usar git reset

MAS:

Eu encontrei este ótimo post que realmente adiciona o comando Git (bem um alias) para git unadd: veja git unadd para detalhes ou ..

Simplesmente,

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

Agora você pode

git unadd foo.txt bar.txt
55
electblake

git remove ou git rm pode ser usado para isso, com o sinalizador --cached. Experimentar:

git help rm
46
gnud

Use git add -i para remover arquivos recém-adicionados do seu próximo commit. Exemplo:

Adicionando o arquivo que você não queria:

$ 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)
# [...]#

Indo para o add interativo para desfazer o seu add (os comandos digitados no git aqui são "r" (revert), "1" (a primeira entrada na lista reverte shows), 'return' para sair do modo revert e "q" (Sair):

$ 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.
$

É isso aí! Aqui está sua prova, mostrando que "foo" está de volta na lista não acompanhada:

$ 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

Aqui está uma maneira de evitar esse problema irritante quando você inicia um novo projeto:

  • Crie o diretório principal para o seu novo projeto.
  • Execute o git init.
  • Agora crie um arquivo .gitignore (mesmo se estiver vazio).
  • Confirme seu arquivo .gitignore.

O Git dificulta muito o git reset se você não tem nenhum commit. Se você criar um pequeno commit inicial apenas por ter um, depois disso você pode git add -A e git reset quantas vezes quiser para fazer tudo certo.

Outra vantagem deste método é que, se você se deparar com problemas de fim de linha mais tarde e precisar atualizar todos os seus arquivos, será fácil:

  • Confira esse commit inicial. Isso removerá todos os seus arquivos.
  • Então confira o seu commit mais recente novamente. Isso recuperará cópias novas de seus arquivos, usando suas configurações atuais de final de linha.
37
Ryan Lundy

Talvez o Git tenha evoluído desde que você postou sua pergunta.

$> git --version
git version 1.6.2.1

Agora você pode tentar:

git reset HEAD .

Isso deve ser o que você está procurando.

33
Kokotte23

Observe que, se você não conseguir especificar uma revisão, precisará incluir um separador. Exemplo do meu 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>

(versão 1.7.5.4 do git)

33
powlo

Para remover novos arquivos da área de preparação (e somente no caso de um novo arquivo), como sugerido acima:

git rm --cached FILE

Use rm --cached apenas para novos arquivos adicionados acidentalmente.

30
Ran

Para redefinir todos os arquivos em uma pasta específica (e suas subpastas), você pode usar o seguinte comando:

git reset *
24
Zorayr

use o comando * para manipular vários arquivos por vez

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

etc

24
boulder_ruby

Apenas digite git reset ele irá reverter e é como se você nunca tivesse digitado git add . desde seu último commit. Certifique-se de ter cometido antes.

22
Donovan

Suponha que eu crie um novo arquivo newFile.txt.

 enter image description here

Suponha que eu adicione o arquivo acidentalmente, git add newFile.txt

 enter image description here

Agora eu quero desfazer esse add, antes de commitar, git reset newFile.txt

 enter image description here

18
Vidura Mudalige

Para um arquivo específico:

  • git reset my_file.txt
  • git checkout my_file.txt

Para todos os arquivos adicionados:

  • git reset.
  • git checkout.

Nota: checkout altera o código nos arquivos e passa para o último estado atualizado (confirmado). reset não altera os códigos; apenas restaura o cabeçalho.

17
Hasib Kamal

Para desfazer uso adicionar

git reset filename

13
Anirudh Sood

Este comando irá unstash suas alterações:

git reset HEAD filename.txt

Você também pode usar

git add -p 

para adicionar partes de arquivos.

13
wallerjake

Estou surpreso que ninguém mencione o modo interativo:

git add -i

escolha a opção 3 para adicionar arquivos. No meu caso, muitas vezes eu quero adicionar mais de um arquivo, com o modo interativo, você pode usar números como este para adicionar arquivos. Isso levará tudo menos 4: 1,2,3,5

Para escolher uma sequência, basta digitar 1-5 para levar de 1 a 5.

Arquivos de teste do Git

13
Jonathan

git add myfile.txt # isto adicionará seu arquivo na lista de confirmação

Muito oposto a este comando é,

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

então, você estará em estado anterior. especificado será novamente na lista untracked (estado anterior).

ele irá redefinir sua cabeça com esse arquivo especificado. então, se a sua cabeça não tem, significa que ela simplesmente irá resetar

9
Silent Spectator
git reset filename.txt

Removerá um arquivo denominado filename.txt do índice atual, a área "prestes a ser confirmada", sem alterar nada.

9
Rahul Sinha

No SourceTree você pode fazer isso facilmente através do gui. Você pode verificar qual comando o sourcetree usa para desassociar um arquivo.

Eu criei um novo arquivo e o adicionei ao git. Então eu desenrolei usando o guia do SourceTree. Este é o resultado:

Desvendar arquivos [08/12/15 10:43]
git -c diff.mnemonicprefix = false -c core.quotepath = false -c credential.helper = restauração de sourcetree -q - caminho/para/arquivo/nome_do_arquivo.Java

O SourceTree usa reset para desassociar arquivos novos.

8
miva2
git reset filename.txt  

Removerá um arquivo denominado filename.txt do índice atual, a área "prestes a ser confirmada", sem alterar nada.

7
Joseph Mathew

Uma das soluções mais intuitivas é usar SourceTree .

Você pode simplesmente arrastar e soltar os arquivos de staged e unstaged  enter image description here

7
Marcin Szymczak

O comando git reset ajuda você a modificar a área de preparação ou a área de preparação e a árvore de trabalho. A habilidade do Git de criar commits exatamente como você quer significa que às vezes você precisa desfazer mudanças nas mudanças que você fez com o git add.

Você pode fazer isso chamando git reset HEAD <file to change>. Você tem duas opções para se livrar completamente das alterações. git checkout HEAD <file(s) or path(s)> é uma maneira rápida de desfazer alterações na área de preparação e na árvore de trabalho. Tenha cuidado com esse comando, no entanto, porque ele remove todas as alterações na sua árvore de trabalho. O Git não sabe sobre essas mudanças, uma vez que elas nunca foram confirmadas. Não há como recuperar essas alterações depois de executar este comando.

Outro comando à sua disposição é git reset --hard. É igualmente destrutivo para a sua árvore de trabalho - quaisquer alterações não confirmadas ou alterações em etapas são perdidas após a execução. Executar git reset -hard HEAD faz a mesma coisa que git checkout HEAD. Apenas não requer um arquivo ou caminho para o trabalho.

Você pode usar --soft com git reset. Ele redefine o repositório para o commit especificado por você e realiza todas essas mudanças. Quaisquer alterações que você já tenha efetuado não são afetadas, nem as alterações em sua árvore de trabalho.

Finalmente, você pode usar o --mixed para redefinir a árvore de trabalho sem testar quaisquer alterações. Isso também desassocia as alterações que são testadas.

1
SAIguru011