Como faço para desfazer 'git add' antes de cometer?
-
20-08-2019 - |
Pergunta
Eu erroneamente arquivos para git usando o comando de adição:
git add myfile.txt
Eu ainda não executar git commit
. Existe uma maneira de desfazer isso, então esses arquivos não serão incluídos no cometer?
Solução
Você pode desfazer git add
antes de cometer com
git reset <file>
que irá removê-lo do índice atual (a lista "prestes a ser cometido") sem alterar qualquer outra coisa.
Você pode usar
git reset
sem qualquer nome de arquivo para unstage todas as alterações devidas. Isto pode vir a calhar quando há muitos arquivos a serem listados, um por um em uma quantidade razoável de tempo.
Em versões antigas do Git, os comandos acima são equivalentes a git reset HEAD <file>
e git reset HEAD
respectivamente, e irá falhar se HEAD
é indefinido (porque você ainda não fez nenhum commit em sua repo) ou ambíguas (porque você criou um ramo chamado HEAD
, que é uma coisa estúpida que você não deve fazer). Este foi mudado em Git 1.8. 2 , embora, por isso em versões modernas de Git você pode usar os comandos acima mesmo antes de fazer sua primeira cometer:
"git reset" (sem opções ou parâmetros) usadas ao erro quando você não tem nenhum commit na sua história, mas dá-lhe agora um índice vazio (para corresponder inexistente cometer você não está mesmo diante).
Outras dicas
Você quer:
git rm --cached <added_file_to_undo>
Raciocínio:
Quando eu era novo para isso, eu primeiro tentou
git reset .
(para desfazer toda a minha add inicial), apenas para obter esse (não tão) mensagem útil:
fatal: Failed to resolve 'HEAD' as a valid ref.
Acontece que este é porque a cabeça ref (ramo?) Não existe até após o primeiro cometer. Ou seja, você vai correr em problema o mesmo para iniciantes como me se o seu fluxo de trabalho, como o meu, era algo como:
- cd para minha grande novo diretório do projeto para experimentar Git, o novo gostosura
-
git init
-
git add .
-
git status
... lotes de pergaminhos porcaria por ...
=> Droga, eu não queria adicionar tudo isso.
-
google "undo git add"
=> encontrar Stack Overflow - yay
-
git reset .
=> fatal:. Não conseguiu resolver 'cabeça' como um ref válida
Acontece ainda que há um bug registrado contra o unhelpfulness deste na lista de discussão.
E que a solução correta foi ali mesmo na saída de status Git (que, sim, eu encoberto como 'porcaria)
... # Changes to be committed: # (use "git rm --cached <file>..." to unstage) ...
E a solução de fato é usar git rm --cached FILE
.
Observe as advertências em outros lugares aqui - git rm
exclui sua cópia de trabalho local do arquivo, mas não se você usar - Em cache . Aqui está o resultado de git help rm
:
- em cache Use esta opção para caminhos unstage e remover apenas a partir do índice. Trabalhando arquivos de árvore, modificados ou não, será deixado.
Eu continuar a usar
git rm --cached .
para remover tudo e começar de novo. não funcionou, porém, porque enquanto add .
é recursiva, acaba necessidades rm
-r
ao recurse. Suspiro.
git rm -r --cached .
Ok, agora eu estou de volta para onde eu comecei. Da próxima vez eu vou usar -n
fazer uma seca correr e ver o que vai ser adicionados:
git add -n .
I fechado acima de tudo para um lugar seguro antes de confiar git help rm
sobre o --cached
não destruir qualquer coisa (e que se eu grafada-lo).
Se você digitar:
git status
git vai dizer o que é encenado, etc, incluindo instruções sobre como unstage:
use "git reset HEAD <file>..." to unstage
Eu acho git faz um trabalho muito bom de empurrando-me para fazer a coisa certa em situações como esta.
Nota: versões git Recentes (1.8.4.x) mudaram esta mensagem:
(use "git rm --cached <file>..." to unstage)
Para esclarecer: git add
move alterações a partir do diretório de trabalho atual para o área de teste (índice).
Este processo é chamado encenar . Assim, o comando mais natural para estágio as mudanças (arquivos alterados) é o óbvio:
git stage
git add
é apenas um mais fácil de digitar alias para git stage
coitado não há comandos git unstage
nem git unadd
. A única relevante é mais difícil de adivinhar ou lembrar,
mas é bastante óbvio:
git reset HEAD --
Podemos facilmente criar um alias para o seguinte:
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
Uma adição para a resposta aceita, se o arquivo erroneamente adicionado era enorme, você provavelmente vai notar que, mesmo depois de a retirar do índice com 'git reset
', ele ainda parece ocupar espaço no diretório .git
. Isso não é nada para se preocupar, o arquivo é de fato ainda no repositório, mas apenas como um "objeto solto", ele não será copiado para outros repositórios (via clone, push), eo espaço será finalmente recuperada - embora talvez não seja muito em breve. Se você está ansioso, você pode executar:
git gc --prune=now
Atualização (o que se segue é a minha tentativa de limpar alguma confusão que pode surgir na maior parte das respostas up-votaram):
Então, qual é o verdadeiro Desfazer de git add
?
git reset HEAD <file>
?
ou
git rm --cached <file>
?
A rigor, e se eu não estou enganado: nenhum .
git add
não pode ser desfeita ??strong> -. Forma segura, em geral
Vamos recordar primeiro o que git add <file>
realmente faz:
-
Se
<file>
era não rastreada anteriormente ,git add
adiciona-lo para o cache , com o seu conteúdo atual. -
Se
<file>
era já monitorados ,git add
salva o conteúdo atual (instantâneo, versão) para o cache. Em GIT, esta ação ainda é chamado Adicionar , (não mero Atualização -lo), porque duas versões diferentes (instantâneos) de um arquivo são considerados como dois itens diferentes: assim, estamos realmente adicionando um novo item para o cache, a ser eventualmente cometido mais tarde.
À luz disto, a questão é um pouco ambígua:
Eu erroneamente arquivos usando o comando adicionado ...
cenário do OP parece ser o primeiro (arquivo untracked), queremos que o "undo" para remover o arquivo (não apenas o conteúdo atual) a partir dos itens rastreados. Se este é o caso, então é ok para executar git rm --cached <file>
.
E nós também poderia correr git reset HEAD <file>
. Isto é, em geral preferível, porque ele funciona em ambos os cenários:. Ele também faz a desfazer quando erroneamente adicionada uma versão de um item já monitorados
Mas há duas ressalvas.
Primeiro: Há (como fora 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, realmente, este um caso praticamente irrelevante.
Segundo: Esteja ciente de que git reset HEAD
não pode recuperar magicamente o conteúdo do arquivo previamente em cache, ele apenas Resyncs-lo da cabeça. Se a nossa git add
equivocada substituiu uma anterior encenado versão não confirmada, não podemos recuperá-lo. É 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 nós basta seguir o fluxo de trabalho preguiçoso usual de fazer 'add git' apenas para a adição de novos arquivos (caso 1), e nós atualizamos novos conteúdos através do cometem, comando git commit -a
.
* (Edit: o acima é praticamente correto, mas ainda pode haver algumas maneiras ligeiramente hackish / complicado para recuperar alterações que foram encenadas, mas não comprometidos e depois substituídos - ver os comentários por Johannes Matokic e iolsmit)
git rm --cached . -r
vai "un-add" tudo que você adicionou a partir do seu diretório atual de forma recursiva
Desfazer um arquivo que já adicionado é muito fácil usando git , para repor myfile.txt
que já adicionado, use:
git reset HEAD myfile.txt
Explique:
Depois de encenado arquivo não desejado (s), para desfazer, você pode fazer git reset
, Head
é cabeça de seu arquivo no local e o último parâmetro é o nome do seu arquivo.
Eu crio os passos na imagem abaixo em mais detalhes para você, incluindo todas as etapas que podem acontecer nestes casos:
Executar
git gui
e remover todos os arquivos manualmente ou selecionando todos eles e clicando no unstage de cometer botão.
Git tem comandos para cada imagináveis ??ação, mas precisa de amplo conhecimento para fazer as coisas direito e por isso é um contra-senso no melhor ...
O que você fez antes:
- Mudou um arquivo e
git add .
usado, ougit add <file>
.
O que você quer:
-
Remova o arquivo do índice, mas mantê-lo com controle de versão e saiu com alterações não confirmadas na cópia de trabalho:
git reset head <file>
-
Redefinir o arquivo para o último estado da HEAD, desfazer alterações e removê-los a partir 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>
Isto é necessário uma vez
git reset --hard HEAD
não funcionará com arquivos individuais. -
Remove
<file>
do índice e controle de versão, mantendo o arquivo versionado-un com as mudanças na cópia de trabalho:git rm --cached <file>
-
Remove
<file>
da cópia de trabalho e controle de versão completamente:git rm <file>
A questão não está claramente colocada. A razão é que git add
tem dois significados:
- adicionando um novo arquivo para a área de teste, em seguida, desfazer com
git rm --cached file
. - adicionando um modificado arquivo para a área de teste, em seguida, desfazer com
git reset HEAD file
.
em caso de dúvida, use
git reset HEAD file
Porque faz a coisa esperado em ambos os casos.
Aviso: se você fizer git rm --cached file
em um arquivo que foi modificado (um arquivo que existia antes no repositório), então o arquivo será removido em git commit
! Ele ainda vai existir em seu sistema de arquivos, mas se mais alguém puxa seu commit, o arquivo será excluído da sua árvore de trabalho.
git status
vai dizer se o arquivo foi um novo arquivo 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
Se você está no seu cometer inicial e você não pode usar git reset
, simplesmente declarar "falência Git" e excluir a pasta .git
e começar de novo
De acordo com muitas das outras respostas você pode usar git reset
MAS:
Eu encontrei este ótimo post pouco que realmente adiciona o comando Git (bem um alias) para git unadd
: veja git unadd para mais detalhes ou ..
Simplesmente,
git config --global alias.unadd "reset HEAD"
Agora você pode
git unadd foo.txt bar.txt
git remove
ou git rm
pode ser usado para isso, com a bandeira --cached
. Tente:
git help rm
Use git add -i
para remover arquivos recém-adicionados a partir de seu próximo cometeu. Exemplo:
Como adicionar o arquivo que você não quer:
$ 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 add interativo para desfazer sua add (os comandos digitados no git aqui estão "r" (revert), "1" (primeira entrada nos shows lista Reverter), 'retorno' para deixar cair fora do modo de reverter, 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á a sua prova, mostrando que "foo" está de volta na lista untracked:
$ 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)
$
Aqui está uma maneira de evitar esse problema irritante quando você iniciar um novo projeto:
- Crie o diretório principal para seu novo projeto.
- Executar
git init
. - Agora crie um arquivo .gitignore (mesmo que seja vazia).
- Commit seu arquivo .gitignore.
Git torna realmente difícil de fazer git reset
se você não tem nenhum commit. Se você criar uma minúscula inicial comprometer apenas por uma questão de ter um, depois que você pode git add -A
e git reset
como muitas vezes quiser, a fim de obter tudo certo.
Outra vantagem deste método é que, se você tiver problemas de delimitação de linhas posteriores e necessidade de atualizar todos os seus arquivos, é fácil:
- Confira que commit inicial. Isto irá remover todos os seus arquivos.
- Em seguida, verificar o seu mais recente cometer novamente. Isso irá recuperar cópias novas de seus arquivos, usando suas configurações de delimitação de linhas atuais.
Talvez Git tem 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.
Note que se você não conseguir especificar uma revisão em seguida, você tem que 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>
(git versão 1.7.5.4)
Para remover novos arquivos da área de teste (e apenas em caso de um novo arquivo), como sugerido acima:
git rm --cached FILE
Use rm --cached apenas para novos arquivos acidentalmente adicionados.
Para repor todos os arquivos em uma pasta particular (e suas subpastas), você pode usar o seguinte comando:
git reset *
usar o comando *
de lidar com vários arquivos ao mesmo tempo
git reset HEAD *.prj
git reset HEAD *.bmp
git reset HEAD *gdb*
etc
tipo Apenas git reset
ele vai voltar e é como se você nunca digitou git add .
desde seu último commit. Certifique-se de você cometeu antes.
Para um arquivo específico:
- git reset meu_arquivo.txt
- git checkout meu_arquivo.txt
Para todos os arquivos adicionados:
- git reset.
- git checkout.
Nota: Checkout altera o código nos arquivos e move-se para o último estado atualizado (comprometido). reset não altera os códigos; É apenas repõe o cabeçalho.
Este comando irá unstash as alterações:
git reset HEAD filename.txt
Você também pode usar
git add -p
para adicionar partes de arquivos.
Eu estou surpreso que nenhum modo interativo uma menção:
git add -i
escolha a opção 3 para arquivos add un. No meu caso eu muitas vezes quiser adicionar mais de um arquivo, com o modo interativo, você pode usar números como este para adicionar arquivos. Isso vai levar todos, mas 4: 1,2,3,5
Para escolher uma seqüência basta digitar 1-5 para levar tudo a partir de 1 a 5.
Para desfazer uso add git
git reset filename
git reset filename.txt
Irá remover um arquivo chamado filename.txt do índice atual, o "prestes a ser cometido" área, sem alterar qualquer outra coisa.
git add myfile.txt
# isto irá adicionar seu arquivo em ser lista comprometido
Muito oposto a este comando é,
git reset HEAD myfile.txt # this will undo it.
Assim, você estará em estado anterior. especificada será novamente na lista de untracked (estado anterior).
que irá redefinir a sua cabeça com esse arquivo especificado. assim, se sua cabeça não tem meios, ele vai simplesmente redefini-lo
Em SourceTree você pode fazer isso facilmente através da gui. Você pode verificar qual comando usa sourcetree para unstage um arquivo.
Eu criei um novo arquivo e acrescentou que para git. Então eu unstaged-lo usando o gui SourceTree. Este é o resultado:
Os arquivos Unstaging [08/12/15 10:43]
git -c diff.mnemonicprefix = false core.quotepath -c = false credential.helper -c = q redefinição sourcetree - path / to / file / filename.java
SourceTree usa reset
para novos arquivos unstage.
Uma das soluções mais intuitivas está usando SourceTree .
Você pode simplesmente arrastar e soltar arquivos a partir encenado e unstaged