Desagrupar um arquivo excluído no git

504

Geralmente, para descartar as alterações em um arquivo, você faria:

git checkout -- <file>

E se a alteração que eu quiser descartar estiver excluindo o arquivo? A linha acima daria um erro:

error: pathspec '<file>' did not match any file(s) known to git.

Qual comando restaurará esse arquivo único sem desfazer outras alterações?

ponto de bônus: Além disso, e se a alteração que eu quiser descartar estiver adicionando um arquivo? Eu gostaria de saber como desfazer essa mudança também.

lurscher
fonte
1
Descartar mudanças e desestagiar são duas coisas diferentes, o que você está tentando fazer?
Andrew Marshall
1
Essas são duas perguntas e problemas diferentes em um post. Isso torna as respostas muito e desnecessariamente confusas.
David Sopko

Respostas:

779

Supondo que você queira desfazer os efeitos git rm <file>ou ser rm <file>seguido por git add -Aalgo semelhante:

# this restores the file status in the index
git reset -- <file>
# then check out a copy from the index
git checkout -- <file>

Para desfazer git add <file>, a primeira linha acima é suficiente, supondo que você ainda não tenha confirmado.

Twalberg
fonte
70
A --é a chave. git reset <file>não funciona, e foi isso que me trouxe aqui.
2
Por que é end-of-options-markernecessário apenas no caso de arquivo excluído?
haridsv
5
@handsv Não é estritamente necessário (você pode fazer alternativamente git reset HEAD <file>, o que é equivalente), mas git resettrata seu primeiro argumento antes end-of-options-markercomo um nome ref, não como um nome de arquivo. Poderia ser escrito um pouco mais flexível? Provavelmente. Por que não foi? Provavelmente apenas os desenvolvedores sabem ao certo.
Twalberg
2
@twalberg git reset filenamefunciona bem para arquivos não excluídos.
Brian Gordon
1
@AaronMahan - você pode explicar a diferença entre git reset <file>e git reset -- <file>. Estou com dificuldade para encontrar uma resposta para isso no google.
21419 Neeraj B.
56

Ambas as perguntas são respondidas em git status.

Para desestabilizar a adição de um novo arquivo, use git rm --cached filename.ext

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

Para desfazer a exclusão de um arquivo, use git reset HEAD filename.ext

# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   deleted:    test

Por outro lado, git checkout --nunca no palco, apenas descarta as alterações que não estão em etapas.

seppo0010
fonte
5
Não vejo a dica para um arquivo excluído no git 1.7.2.5 no Debian.
tripleee
É bom ver git statuscitado; mostra aos usuários uma maneira de auto-ajuda agora e na próxima vez, e caso as informações sejam adicionadas ou atualizadas em versões futuras do git.
Will Caim
Isto está errado. "Alterações a serem confirmadas" é o que você vê antes do git reset.Após o git reset, você verá "Alterado, mas não atualizado", o que significa "Alterações não testadas" no idioma nativo dos autores do git, aparentemente. Mais importante, todo o dogma sobre "o status git diz tudo o que você sabe" é uma mentira. (Gerentes que dizem que está desperdiçando o tempo das pessoas e deve ser demitido.)
personal_cloud
11

As respostas para suas duas perguntas estão relacionadas. Vou começar com o segundo:

Depois de preparar um arquivo (geralmente com git add, embora alguns outros comandos também incluam implicitamente as alterações git rm), você pode fazer o backup dessa alteração git reset -- <file>.

No seu caso, você deve ter utilizado git rmpara remover o arquivo, o que equivale a simplesmente removê-lo rme, em seguida, organizar essa alteração. Se você o desestabilizar primeiro, git reset -- <file>poderá recuperá-lo git checkout -- <file>.

Ben Jackson
fonte
7

Se ele foi preparado e confirmado, o seguinte redefinirá o arquivo:

git reset COMMIT_HASH file_path
git checkout COMMIT_HASH file_path
git add file_path

Isso funcionará para uma exclusão que ocorreu várias confirmações anteriores.

michaeldever
fonte
1
É mais eficiente paragit revert COMMIT_HASH
Flair
2

No git v2.23 , você tem outra opção:

git restore --staged -- <file>

Kreempuff
fonte