Várias maneiras de remover alterações locais do Git

625

Acabei de clonar um repositório git e fazer check-out de um ramo. Eu trabalhei nele e, em seguida, decidi remover todas as minhas alterações locais, pois queria a cópia original.

Em resumo, eu tive que executar os dois comandos a seguir para remover minhas alterações locais

git checkout .

git clean -f

Minha pergunta é,

(1) Essa é a abordagem correta para se livrar das alterações locais, ou então, deixe-me saber a abordagem correta.

(2) quando usamos git reset --hardcomo posso redefinir mesmo sem esse comando

obrigado

* Solução: Principais edições: 26/03: * Substituídos muitos termos vagos pela terminologia específica do git [rastreada / não rastreada / encenada / não encenada]

Pode haver apenas três categorias de arquivos quando fazemos alterações locais:

Tipo 1. Arquivos rastreados em estágios

Tipo 2. Arquivos rastreados em estágios

Tipo 3. Arquivos não rastreados em estágios, também conhecidos como arquivos não rastreados

  • Preparado - aqueles que são movidos para a área intermediária / adicionados ao índice
  • Arquivos modificados rastreados
  • Não rastreado - novos arquivos. Sempre sem palco. Se preparado, isso significa que eles são rastreados.

O que cada comando faz:

  1. git checkout . - Remove SOMENTE arquivos rastreados em estágios [Tipo 2]

  2. git clean -f - Remove somente arquivos não rastreados em estágios [Tipo 3]

  3. git reset --hard - Remove APENAS arquivos rastreados em etapas e não em etapas [Type 1, Type 2]

  4. git stash -u - Remove todas as alterações [Tipo 1, Tipo 2, Tipo 3]

Conclusão:

Está claro que podemos usar

(1) combination of `git clean -f` and `git reset --hard` 

OU

(2) `git stash -u`

para alcançar o resultado desejado.

Nota: Esconder, como a palavra significa 'Armazenar (algo) de forma segura e secreta em um local especificado'. Isso sempre pode ser recuperado usando git stash pop. Portanto, escolher entre as duas opções acima é uma decisão do desenvolvedor.

Obrigado Christoph e Frederik Schøning.

Edição: 27/03

Eu pensei que vale a pena colocar a nota ' cuidado ' paragit clean -f

git clean -f

Não há retorno. Use -nou --dry-runpara visualizar o dano que você causará.

Se você também deseja remover diretórios, execute git clean -f -d

Se você deseja apenas remover arquivos ignorados, execute git clean -f -X

Se você deseja remover arquivos ignorados e não ignorados, execute git clean -f -x

reference: more on git clean: Como remover arquivos locais (não rastreados) da árvore de trabalho atual do Git?

Edição: 20/05/15

Descartando todas as confirmações locais neste ramo [Removendo confirmações locais]

Para descartar todas as confirmações locais nesta ramificação, para tornar a ramificação local idêntica ao "upstream" dessa ramificação, basta executar git reset --hard @{u}

Referência: http://sethrobertson.github.io/GitFixUm/fixup.html

ou faça git reset --hard origin/master[se a filial local for master]

Nota: 06/12/2015 Esta não é uma duplicata da outra pergunta SO marcada como duplicada. Esta questão aborda como remover alterações locais do GIT [remover um arquivo adicionado, remover alterações adicionadas ao arquivo existente etc. e as várias abordagens; Onde no outro encadeamento SO aborda apenas como remover a consolidação local. Se você adicionou um arquivo e deseja removê-lo sozinho, o outro encadeamento SO não discute sobre ele. Portanto, este não é um duplicado do outro]

Edição: 23/06/15

Como reverter uma confirmação já enviada para um repositório remoto?

$ git revert ab12cd15

Edição: 01/09/2015

Excluir uma confirmação anterior da filial local e da filial remota

Caso: Você acabou de cometer uma alteração em sua filial local e imediatamente empurrou para a filial remota, de repente percebeu: Oh não! Eu não preciso dessa mudança. Agora faz o que?

git reset --hard HEAD~1 [para excluir essa confirmação da filial local]

git push origin HEAD --force[ambos os comandos devem ser executados. Para excluir da filial remota]

Qual é o ramo? É o ramo atualmente com check-out.

Editar 09/08/2015 - Remover mesclagem local do git :

Estou no masterramo e mesclado masterramo com um ramo recentemente trabalhandophase2

$ git status
# On branch master

$ git merge phase2

$ git status
# On branch master
# Your branch is ahead of 'origin/master' by 8 commits.

P: Como se livrar dessa mesclagem? Tentei git reset --hard e git clean -d -f ambos não funcionaram.

A única coisa que funcionou são as seguintes:

$ git reset --hard origin/master

ou

$ git reset --hard HEAD~8

ou

$ git reset --hard 9a88396f51e2a068bb7 [sha commit code - este é o que estava presente antes que todas as suas confirmações de mesclagem acontecessem]

homem Aranha
fonte
1
Eu acho que este tópico pode responder às suas perguntas: stackoverflow.com/questions/1146973/…
Saucier
1
O "git stash" removerá todas as alterações que você fez.
precisa
1
Bom resumo! Eu adicionaria outra categoria de arquivo: "Digite 4. Arquivos ignorados". git stash -a[ou --all] também esconderá os arquivos ignorados e não rastreados. git clean -xirá limpar arquivos ignorados também. git clean -Xirá limpar apenas os arquivos ignorados.
precisa saber é o seguinte
2
@JavaDev Sua pergunta foi mais como uma resposta. Agradecemos que você tenha continuado editando e compilando todas as respostas.
precisa saber é o seguinte
1
graças eu corri todos os 4 de seus comandos para reverter alterações locais
Vincent Tang

Respostas:

505

Tudo depende exatamente do que você está tentando desfazer / reverter. Comece lendo a postagem no link da Ube . Mas para tentar uma resposta:

Reinicialização total

git reset --hard [HEAD]

remova completamente todas as alterações em etapas e em etapas nos arquivos rastreados.

Eu me vejo frequentemente usando redefinições rígidas, quando penso "desfazer tudo como se eu tivesse feito uma re-clone completa do controle remoto". No seu caso, onde você apenas deseja que seu repo seja intocado, isso funcionaria.

Limpar \ limpo

git clean [-f]

Remova arquivos que não são rastreados.

Para remover arquivos temporários, mas mantenha as alterações em etapas e em etapas nos arquivos já rastreados. Na maioria das vezes, eu provavelmente acabaria fazendo uma regra de ignorar em vez de limpar repetidamente - por exemplo, para as pastas bin / obj em um projeto C #, que você normalmente deseja excluir do seu repositório para economizar espaço, ou algo assim.

A opção -f (force) também removerá os arquivos que não são rastreados e também estão sendo ignorados pelo git, apesar da regra de ignorar. No caso acima, com uma regra de ignorar para nunca rastrear as pastas bin / obj, mesmo que essas pastas estejam sendo ignoradas pelo git, o uso da opção force os removerá do seu sistema de arquivos. Eu vi esporadicamente uma utilidade para isso, por exemplo, ao implantar scripts, e você deseja limpar seu código antes de implantar, fechar ou o que for.

O Git clean não toca em arquivos que já estão sendo rastreados.

Caixa "ponto"

git checkout .

Na verdade, eu nunca tinha visto essa notação antes de ler sua postagem. Estou com dificuldade para encontrar documentação para isso (talvez alguém possa ajudar), mas, ao brincar um pouco, parece que isso significa:

"desfazer todas as alterações na minha árvore de trabalho".

Ou seja, desfaça as alterações não faseadas nos arquivos rastreados. Aparentemente, ele não toca em alterações faseadas e deixa os arquivos não rastreados em paz.

Esconderijo

Algumas respostas mencionam esconderijo. Como a redação indica, você provavelmente usaria stashing quando estiver no meio de algo (não está pronto para uma confirmação) e precisará alternar temporariamente ramos ou trabalhar de alguma forma em outro estado do seu código, mais tarde, para retornar ao seu "desarrumado" escrivaninha". Não vejo isso se aplica à sua pergunta, mas é definitivamente útil.

Resumindo

Geralmente, se você está confiante de que se comprometeu e talvez tenha levado a mudanças remotas importantes, se estiver apenas brincando ou algo semelhante, o uso de git reset --hard HEADseguido por git clean -flimpará definitivamente seu código para o estado, ele estaria, caso tivesse sido clonado e fez check-out de uma filial. É realmente importante enfatizar que a redefinição também removerá as alterações faseadas, mas não confirmadas. Ele limpará tudo o que não foi confirmado (exceto arquivos não rastreados, nesse caso, use clean ).

Todos os outros comandos existem para facilitar cenários mais complexos, nos quais é necessária uma granularidade de "desfazer coisas" :)

Sinto que a sua pergunta nº 1 está coberta, mas, por fim, para concluir a nº 2: a razão pela qual você nunca encontrou a necessidade de usar git reset --hardfoi que nunca havia realizado nada. Se você tivesse realizado uma mudança, git checkout .nem git clean -fteria revertido isso.

Espero que isso cobre.

Frederik Struck-Schøning
fonte
Obrigado pela razão do uso git reset --hard. Eu tentei sair, e sim .. esses arquivos adicionados ao índice (estadiamento) foram removidos somente depois git reset --hard, e eu suponho que por padrão git reset --hardé git reset --hard head. Este link também foi útil gitready.com/beginner/2009/01/18/the-staging-area.html
spiderman
Melhorei minha resposta por que acho que git stash -ufaz mais sentido aqui.
Christoph
2
Obrigado a vocês dois. Resumi a resposta e integrei a minha pergunta. Christoph me informou o que git stash -ufaz e como exibi-lo, mas Frederik me informou que redefinir muito e usar a combinação de git reset --harde git clean -f, e por que não, stashé preferido em alguns cenários. Agora, por favor me ajude a escolher qual deles devo marcar como Resposta :), ambas são minhas respostas.
spiderman
3
.é um pathspec que se refere ao diretório de trabalho atual, que pode ser a raiz do repositório. From git-scm.com: git checkout [<tree-ish>] [--] <pathspec>…atualiza os caminhos nomeados na árvore de trabalho do arquivo de índice ou de um <tree-ish> nomeado.
precisa saber é o seguinte
3
Nunca é estressado o suficiente que ambos git reset --harde git clean -dfxsimilares são destrutivos . De qualquer forma, corrija a letra minúscula headna resposta, ela deve estar em maiúscula HEADou não estar presente.
Pavel Šimerda
25

Razão para adicionar uma resposta neste momento:

Até agora, eu estava adicionando a conclusão e as 'respostas' à minha pergunta inicial, tornando a pergunta muito longa, passando a separar a resposta.

Também adicionei comandos git usados ​​com mais freqüência que me ajudam no git, para ajudar outra pessoa também.

Basicamente, para limpar todos os commits locais $ git reset --harde $ git clean -d -f


O primeiro passo antes de fazer qualquer confirmação é configurar seu nome de usuário e email que aparecem junto com o seu commit.

#Define o nome que você deseja anexar às suas transações de confirmação

$ git config --global user.name "[name]"

#Define o email que você deseja anexar às suas transações de confirmação

$ git config --global user.email "[email address]"

#Liste a configuração global

$ git config --list

#Liste o URL remoto

$ git remote show origin

#check status

git status

#Liste todas as ramificações locais e remotas

git branch -a

#create uma nova filial local e comece a trabalhar nessa filial

git checkout -b "branchname" 

ou, pode ser feito como um processo de duas etapas

criar ramo: git branch branchname trabalhe neste ramo:git checkout branchname

#commit local changes [processo de duas etapas: - Adicione o arquivo ao índice, o que significa adicionar à área de preparação. Em seguida, confirme os arquivos que estão presentes nesta área de preparação]

git add <path to file>

git commit -m "commit message"

#checkout em alguma outra filial local

git checkout "local branch name"

#remove todas as alterações na ramificação local [Suponha que você tenha feito algumas alterações na ramificação local, como adicionar novo arquivo ou modificar o arquivo existente ou fazer uma confirmação local, mas não precisa mais disso] git clean -d -fe git reset --hard [limpe todas as alterações locais feitas na ramificação local, exceto se confirmação local]

git stash -u também remove todas as alterações

Nota: É claro que podemos usar (1) combinação de git clean –d –fe git reset --hard OR (2) git stash -u para alcançar o resultado desejado.

Nota 1: Esconderijo, pois a palavra significa 'Armazene (algo) de forma segura e secreta em um local especificado'. Isso sempre pode ser recuperado usando o git stash pop. Portanto, escolher entre as duas opções acima é uma decisão do desenvolvedor.

Nota 2: git reset --hardexcluirá as alterações do diretório de trabalho. Guarde todas as alterações locais que deseja manter antes de executar este comando.

# Alterne para o ramo mestre e verifique se você está atualizado.

git checkout master

git fetch [isso pode ser necessário (dependendo da sua configuração do git) para receber atualizações sobre a origem / mestre]

git pull

# Mesclar o ramo do recurso no ramo mestre.

git merge feature_branch

# Redefina a ramificação principal para o estado de origem.

git reset origin/master

# Apagou acidentalmente um arquivo do local, como recuperá-lo? Faça um git statuspara obter o caminho completo do arquivo excluído

git checkout branchname <file path name>

é isso aí!

#Merge master branch with someotherbranch

git checkout master
git merge someotherbranchname

#rename filial local

git branch -m old-branch-name new-branch-name

#delete filial local

git branch -D branch-name

#delete filial remota

git push origin --delete branchname

ou

git push origin :branch-name

#revert um commit já enviado para um repositório remoto

git revert hgytyz4567

#branch de uma consolidação anterior usando GIT

git branch branchname <sha1-of-commit>

#Altere a mensagem de confirmação da confirmação mais recente que já foi enviada para remoto

git commit --amend -m "new commit message"
git push --force origin <branch-name>

# Descartando todas as confirmações locais neste ramo [Removendo confirmações locais]

Para descartar todas as confirmações locais nesta ramificação, para tornar a ramificação local idêntica ao "upstream" dessa ramificação, basta executar

git reset --hard @{u}

Referência: http://sethrobertson.github.io/GitFixUm/fixup.html ou do git reset --hard origin/master[se a filial local for mestre]

# Reverter uma confirmação já enviada para um repositório remoto?

$ git revert ab12cd15

#Excluir uma confirmação anterior da filial local e da filial remota

Caso de uso: você acabou de confirmar uma alteração em sua filial local e imediatamente empurrou para a filial remota, de repente percebeu: Oh não! Eu não preciso dessa mudança. Agora faz o que?

git reset --hard HEAD~1[para excluir essa confirmação da ramificação local. 1 indica o que você fez]

git push origin HEAD --force[ambos os comandos devem ser executados. Para excluir da ramificação remota]. A filial atualmente com check-out será referida como a filial em que você está realizando esta operação.

# Exclua algumas confirmações recentes de repositório local e remoto e preserve a confirmação que deseja. (um tipo de reversão confirmada por local e remoto)

Vamos supor que você tenha 3 confirmações enviadas para a ramificação remota chamada ' develop'

commitid-1 done at 9am
commitid-2 done at 10am
commitid-3 done at 11am. // latest commit. HEAD is current here.

Para reverter para o commit antigo (para alterar o estado da ramificação)

git log --oneline --decorate --graph // para ver todos os seus commids

git clean -d -f // limpa quaisquer alterações locais

git reset --hard commitid-1 // revertendo localmente para este commit

git push -u origin +develop// envia esse estado para remoto. + para fazer força empurrar

# Remover a mesclagem local do git: Caso: Estou na ramificação principal e juntei a ramificação principal com uma ramificação recém-criada phase2

$ git status

No mestre da filial

$ git merge phase2 $ git status

No mestre da filial

Sua filial está à frente de 'origem / mestre' em 8 confirmações.

P: Como se livrar dessa mesclagem git local? Tentei git reset --harde git clean -d -fambos não funcionaram. A única coisa que funcionou são as seguintes:

$ git reset --hard origem / master

ou

$ git reset --hard HEAD ~ 8

ou

$ git reset --hard 9a88396f51e2a068bb7 [sha commit code - este é o que estava presente antes que todas as suas confirmações de mesclagem acontecessem]

#create arquivo gitignore

touch .gitignore // cria o arquivo em usuários mac ou unix

conteúdo da amostra .gitignore:

.project
*.py
.settings

Link de referência à folha de dicas do GIT: https://services.github.com/on-demand/downloads/github-git-cheat-sheet.pdf

homem Aranha
fonte
1
Seu comando para excluir ramificação remota pode não ser o melhor . Você está usando git push origin :branch-nameno entanto eu recomendo usargit push origin --delete branchname
vibs2006 4/17/17
Concordo, i atualizado com sua sugestão, obrigado @ vibs2006
spiderman
21

Como em tudo no git, existem várias maneiras de fazer isso. Os dois comandos que você usou são uma maneira de fazê-lo. Outra coisa que você poderia ter feito é simplesmente escondê-los git stash -u. O -ugarante que arquivos recém-adicionadas (untracked) também estão incluídos.

O mais prático git stash -ué que

  1. provavelmente é o comando único mais simples (apenas?) para atingir seu objetivo
  2. se você mudar de ideia depois, recupera todo o seu trabalho git stash pop(é como excluir um e-mail no gmail, onde você pode desfazer se mudar de ideia depois)

A partir da sua outra pergunta, git reset --hardvocê não removerá os arquivos não rastreados, portanto você ainda precisará do arquivo git clean -f. Mas um git stash -upode ser o mais conveniente.

Christoph
fonte
git reset --hardnão irá remover untracked arquivos de fato, mas irá remover as alterações untracked, ou seja, alterações em arquivos, que já estão no índice. Tenho certeza que isso é o que você quis dizer :)
Frederik Struck-Schöning
Quando usei git stash -u, vi essa resposta do git bash. "Saved diretório de trabalho e estado índice de WIP em {branchname} Pode ser este salvou um é o que poderíamos recuperar usando. git stash pop.
spiderman
Obrigado a vocês dois. Resumi a resposta e integrei a minha pergunta. Christoph me informou o que git stash -ufaz e como exibi-lo, mas Frederik me informou que redefinir muito e usar a combinação de git reset --harde git clean -f, e por que não, stashé preferido em alguns cenários. Agora, por favor me ajude a escolher qual deles devo marcar como Resposta :), ambas são minhas respostas.
spiderman
mas e se houver um arquivo adicionado ao meu repositório que não queira rastrear? apenas no meu repo. Se eu adicioná-lo à lista de ignorados, tenho um arquivo .ignore a confirmar, que afetará todos os outros também.
user20358
7

1. Quando você não deseja manter as alterações locais.

git reset --hard

Este comando removerá completamente todas as alterações locais do seu repositório local. Essa é a melhor maneira de evitar conflitos durante o comando pull, apenas se você não quiser manter as alterações locais.

2. Quando você deseja manter suas alterações locais

Se você deseja obter as novas alterações remotas e ignorar as alterações locais durante essa solicitação,

git stash

Ele esconderá todas as alterações locais, agora você pode obter as alterações remotas,

git pull

Agora, você pode recuperar suas alterações locais,

git stash pop
Actung
fonte
1
git reset --hardnão remove todas as alterações locais. Ele remove apenas as modificações. Se você deseja remover acrescenta, em seguida, você deve tambémgit clean -fd
John Henckel
4

Usar:

git checkout -- <file>

Para descartar as alterações no diretório de trabalho.

Tadas Stasiulionis
fonte
4

Eu acho que o git tem uma coisa que não está claramente documentada. Eu acho que foi realmente negligenciado.

git checkout .

Cara, você salvou meu dia. Eu sempre tenho coisas que quero tentar usar o código modificado. Mas as coisas às vezes acabam atrapalhando o código modificado, adicionam novos arquivos não rastreados etc. Então, o que eu quero fazer é preparar o que quero, fazer as coisas bagunçadas, limpar rapidamente e confirmar se estiver feliz.

Não git clean -fdfunciona bem para arquivos não rastreados.

Em seguida, git resetsimplesmente remove as etapas, mas git checkouté meio complicado demais. Especificar arquivo um por um ou usar diretórios nem sempre é o ideal. Às vezes, os arquivos alterados dos quais quero me livrar estão nos diretórios que desejo manter. Eu desejei esse comando que apenas remove as alterações não-estágios e aqui está você. Obrigado.

Mas acho que eles deveriam ter, git checkoutsem opções, remover todas as alterações não organizadas e não tocar na encenada. É meio modular e intuitivo. Mais como o que git resetfaz. git cleantambém deve fazer o mesmo.

Emmanuel Mahuni
fonte
2

A melhor maneira é verificar as alterações.

Alterando o arquivo pom.xml em um projeto chamado project-name, você pode fazê-lo:

git status

# modified:   project-name/pom.xml

git checkout project-name/pom.xml
git checkout master

# Checking out files: 100% (491/491), done.
# Branch master set up to track remote branch master from origin.
# Switched to a new branch 'master'
bpedroso
fonte
2

Para descartar tudo o que eu gosto de guardar e largar, é a maneira mais rápida de descartar tudo, especialmente se você trabalha entre vários repositórios.

Isso esconderá todas as alterações na {0}chave e a eliminará instantaneamente{0}

git stash && git stash drop

Tatarin
fonte
1

Antes de mais nada, verifique se as alterações importantes foram salvas ou não por:

Status $ git

do que tentar

$ git reset --hard

ele redefinirá sua ramificação para o padrão

mas se você precisar apenas desfazer:

$ edit (1) $ git add frotz.c filfre.c $ mailx (2) $ git reset
(3) $ git pull git: //info.example.com/ nitfol


Leia mais >> https://git-scm.com/docs/git-reset

Rizo
fonte
Nota lateral: comando reset --hard is dangerous, isso removerá todas as alterações e não poderá ser desfeito. O usuário deve estar ciente ao usar a redefinição do hardware.
Danglingpointer