Jogue fora os commits locais no Git

1469

Devido a algumas más escolhas, meu repositório Git local está atualmente cinco commits à frente da origem e não está em bom estado. Eu quero me livrar de todos esses commits e começar de novo.

Obviamente, excluir meu diretório de trabalho e re-clonar faria isso, mas fazer o download de tudo do GitHub novamente parece exagero e não é um bom uso do meu tempo.

Talvez git revertseja o que eu preciso, mas não quero acabar com 10 confirmações antes da origem (ou mesmo seis), mesmo que ele retorne o código ao estado correto. Eu só quero fingir que a última meia hora nunca aconteceu.

Existe um comando simples que fará isso? Parece um caso de uso óbvio, mas não estou encontrando nenhum exemplo disso.


Observe que esta pergunta é especificamente sobre confirmações , não sobre:

  • arquivos não rastreados
  • mudanças sem estágio
  • mudanças encenadas, mas não confirmadas
David Moles
fonte
3
possível duplicata de várias maneiras para remover alterações Git local
Spiderman

Respostas:

2470

Se o excesso de confirmações estiver visível apenas para você, basta fazer git reset --hard origin/<branch_name> o retorno para onde está a origem. Isso redefinirá o estado do repositório para a confirmação anterior e descartará todas as alterações locais.

Fazer um git revertfaz novas confirmações para remover as confirmações antigas de uma maneira que mantém a história de todos sã.

Ben Jackson
fonte
91
git reset --hard <commit hash, branch, or tag>se você quiser ir para uma referência específica que não seja uma filial remota.
Sam Soffes
55
Só para ficar claro, se você não está trabalhando master, mas em outro ramo, você deve executargit reset --hard origin/<your-branch-name>
Zoltán
33
Isso não apenas descartará as confirmações locais, mas também jogará fora tudo na sua árvore de trabalho (ou seja, seus arquivos locais). Se tudo que você quer fazer é uncommit, mas deixe o seu trabalho intacta, você deve fazer "CABEÇA git reset ^" ... por stackoverflow.com/questions/2845731/...
aaronbauman
3
Você pode fazer uma busca depois disso. Isso corrigiu o contador de número de confirmações à espera de serem enviadas no SourceTree.
Stan
2
git reset --hard origin/<branch_name>Ele também redefinirá a configuração do projeto, portanto, cuide disso. Eu tenho um .cfgarquivo grande que foi redefinido para o padrão. Eu tive que passar horas nisso novamente.
MAC
271

Simplesmente exclua seu ramo mestre local e recrie-o da seguinte maneira:

git branch -D master
git checkout origin/master -b master
Ramon Zarazua B.
fonte
2
Isso funciona bem quando o retorno de suas alterações custaria muito tempo, o que aconteceu comigo após algumas reestruturações.
aross 15/05
1
Útil para problemas de puxar / empurrar subárvore entre os membros da equipe!
Jorge Orpinel
Isso é perfeito quando você deseja restaurar um ramo em vez de apenas o mestre.
precisa
1
essa não é uma boa maneira de excluir uma confirmação local única. Melhor usargit reset --hard origin/<branch_name>
Kirit Vaghela 5/16/16
1
Talvez essa solução funcione, mas isso não significa que seja a correta.
Adly
202

Tentar:

git reset --hard <the sha1 hash>

para repor a cabeça onde quer que você esteja. Use o gitk para ver em qual commit você deseja estar. Você também pode redefinir no gitk.

Anders Zommarin
fonte
5
A votação foi positiva, pois é uma informação útil, mas a resposta de Ben Jackson recebe a marca de seleção para resolver exatamente o que eu queria - de uma maneira que não exigia que eu procurasse hashes. :)
David Moles
2
É esse o momento em que sua nova ramificação nunca foi levada à origem ainda #
:
126

Exclua a confirmação mais recente:

git reset --hard HEAD~1

Exclua a confirmação mais recente, sem destruir o trabalho que você fez:

git reset --soft HEAD~1

James L.
fonte
5
Resposta útil. Obrigado! Eu usei git reset --soft origin / master
Tarun Kumar
2
@TarunKumar OBRIGADO! Estou usando a integração do VS, e sua solução foi a única maneira de eliminar vários commits de mesclagem que eu não queria em uma ramificação e não tinha permissão para fazer check-in.
DVK
Obrigado, exatamente o que eu estava procurando, "git reset --soft HEAD ~ 1" fez o trabalho como eu cometi sem querer e queria reverter, mas tinha outros arquivos que não queria que fossem destruídos após a reversão.
Edvard_munch 28/11/19
47

Se você estiver usando o aplicativo Atlassian SourceTree , poderá usar a opção de redefinição no menu de contexto.

insira a descrição da imagem aqui

muruge
fonte
42

Na sua tentativa de ramificação:

git reset --hard origin/<branch_name>

Valide a reversão (para o estado, sem confirmações locais), usando " git log" ou " git status".

parasita
fonte
1
@ Troseph: todas as respostas listadas acima, tentei como está e não obtive o cenário corrigido. A abordagem genérica, que não foi ilustrada em nenhuma das respostas acima, é o que foi tentado responder aqui.
parasrish
3
A resposta aceita é a mesma que a sua, menos o nome de filial genérico, e nos comentários @Zoltan diz explicitamenteJust to be clear, if you're not working on master but on another branch, you should run git reset --hard origin/<your-branch-name>
Troyseph
1
Esta é a melhor resposta na minha opinião.
dwjohnston 26/03
21

git reset --hard @{u}* exclui todas as suas alterações locais na ramificação atual, incluindo confirmações. Estou surpreso que ninguém tenha postado isso ainda, considerando que você não precisará procurar o que se comprometer a reverter ou brincar com os ramos.

* Ou seja, redefina a ramificação atual em - @{upstream}geralmente origin/<branchname>, mas nem sempre

Kevin Chen
fonte
1
Algumas conchas, como o peixe, interpretam o "@", então você pode ter que colocar o '@ {u}' entre aspas, por exemplo, `git reset --hard '@ {u}'. Enfim, boa descoberta!
trysis
Resposta impressionante é incrível
Marko
1
Como você imprime o valor de @ {u}?
Philip Rego
12

Para ver / obter o ID SHA-1 do commit, você também quer voltar

gitk --all

Para reverter para esse commit

git reset --hard sha1_id

!Nota. Todas as confirmações feitas após essa confirmação serão excluídas (e todas as suas modificações no projeto). Então, primeiro é melhor clonar o projeto em outra ramificação ou copiar em outro diretório.

Nicholas
fonte
isso é ótimo para situações em que o controle remoto não está mais disponível e é necessário redefinir para alguma confirmação local. O gitk é incrível - não sabia disso antes.
precisa saber é o seguinte
Se você já está no gitk, basta clicar com o botão direito do mouse no commit e selecionar "redefinir o ramo XY para aqui".
mkrieger1
E as confirmações mais recentes não serão excluídas imediatamente. Não há mais ramo apontando para eles (lembre-se, um ramo nada mais é do que um "marcador" para um commit específico).
mkrieger1
9

Eu tive uma situação em que queria remover uma confirmação que não foi enviada por push, mas a confirmação foi antes de outra. Para fazer isso, usei o seguinte comando

git rebase -i HEAD~2 -> irá refazer os dois últimos commits

E usei 'drop' para a assinatura de confirmação que eu queria remover.

Robert
fonte
9

Remover arquivos não rastreados (alterações locais não confirmadas)

git clean -df

Excluir permanentemente todas as confirmações locais e obter a confirmação remota mais recente

git reset --hard origin/<branch_name>
ElasticCode
fonte
8

Para confirmações locais que não estão sendo enviadas por push, você também pode usar git rebase -ipara excluir ou compactar uma confirmação.

Nikhil Katre
fonte
1
Sei que essa pode não ser a solução mais curta, mas votei com você desde que o IMHO git rebase -ié uma maneira mais genérica de resolver muitos problemas semelhantes e pode ser útil em diversas situações.
Stefan Marinov 31/01
1
Use a droppalavra - chave (em vez de excluir uma linha) ao remover todas as confirmações para evitar a interrupção da rebase.
Michal Čizmazia
6

A solução simples será combinar o ramo principal local HEAD com a origem / ramo principal HEAD

git reset --hard origin/master

PS: origem / mestre - é um ponteiro remoto para o ramo principal. Você pode substituir o mestre por qualquer nome de filial

narwanimonish
fonte
4

Antes de responder, vamos adicionar alguns antecedentes, explicando o que é isso HEAD. uma vez que algumas das opções abaixo resultarão em desanexação da cabeça

First of all what is HEAD?

HEADé simplesmente uma referência ao commit atual (mais recente) no branch atual.
Só pode haver um single HEADa qualquer momento. (excluindo git worktree)

O conteúdo de HEADé armazenado dentro .git/HEADe contém os 40 bytes SHA-1 da confirmação atual.


detached HEAD

Se você não está no último commit, o que significa que HEADestá apontando para um commit anterior no histórico detached HEAD.

insira a descrição da imagem aqui

Na linha de comando, será semelhante a este- SHA-1 em vez do nome do ramo, pois ele HEADnão está apontando para a ponta do ramo atual

insira a descrição da imagem aqui

insira a descrição da imagem aqui

Algumas opções sobre como recuperar de um HEAD desanexado:


git checkout

git checkout <commit_id>
git checkout -b <new branch> <commit_id>
git checkout HEAD~X // x is the number of commits t go back

Isso fará o checkout do novo ramo apontando para o commit desejado.
Este comando fará checkout para um determinado commit.
Nesse ponto, você pode criar uma ramificação e começar a trabalhar a partir deste ponto.

# Checkout a given commit. 
# Doing so will result in a `detached HEAD` which mean that the `HEAD`
# is not pointing to the latest so you will need to checkout branch
# in order to be able to update the code.
git checkout <commit-id>

# create a new branch forked to the given commit
git checkout -b <branch name>

git reflog

Você sempre pode usar o reflogtambém.
git reflogexibirá qualquer alteração que tenha atualizado HEADe o check-out da entrada de reflog desejada HEADretornará a esta confirmação.

Sempre que o HEAD for modificado, haverá uma nova entrada no reflog

git reflog
git checkout HEAD@{...}

Isso o levará de volta ao seu commit desejado

insira a descrição da imagem aqui


git reset --hard <commit_id>

"Mova" seu HEAD de volta para o commit desejado.

# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32

# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts if you've modified things which were
# changed since the commit you reset to.
  • Nota: ( Desde o Git 2.7 ),
    você também pode usá-lo git rebase --no-autostash.

git revert <sha-1>

"Desfazer" o intervalo de confirmação ou confirmação fornecido.
O comando reset irá "desfazer" quaisquer alterações feitas no commit fornecido.
Um novo commit com o patch de desfazer será confirmado enquanto o commit original também permanecerá no histórico.

# add new commit with the undo of the original one.
# the <sha-1> can be any commit(s) or commit range
git revert <sha-1>

Este esquema ilustra qual comando faz o quê.
Como você pode ver lá, reset && checkoutmodifique o arquivo HEAD.

insira a descrição da imagem aqui

CodeWizard
fonte
3

Para os interessados ​​na solução do Visual Studio, aqui está o detalhamento:

  1. Na Team Explorerjanela, conecte-se ao repositório de destino.
  2. Em seguida Branches, em , clique com o botão direito do mouse na filial de interesse e selecione View history.
  3. Clique com o botão direito do mouse em uma confirmação na Historyjanela e escolha Reset -> Delete changes (--hard).

Isso descartará as confirmações locais e redefinirá o estado do seu repo para a confirmação selecionada. Ou seja, suas alterações após a retirada do repositório serão perdidas.

Bozhidar Stoyneff
fonte
2

Se o seu ramo está à frente de ' origin/XXX' em 5 confirma.

Você pode emitir:

git reset --hard HEAD~5

E deve remover os últimos 5 commits.

Ha Choo
fonte
0
git reset --hard <SHA-Code>

Isso será útil se você cometeu alguns erros em sua cópia local e deseja garantir que não seja enviado por push à sua filial remota.

O Código SHA pode ser obtido consultando a versão web do seu painel git para o último commit na ramificação.

Dessa forma, você pode ser sincronizado com a última confirmação na ramificação.

Você pode fazer isso git pulldepois de concluir com êxito a reinicialização completa para confirmar que não há nada novo em sin.

Sua filial está atualizada com Origin/<Branch Name>

Sameer Ashraf
fonte
0

Se você deixar seu repositório local em uma bagunça completa, uma maneira confiável de jogar fora os commits locais no Git é ...

  1. Use "git config --get remote.origin.url" para obter o URL de origem remota
  2. Renomeie a pasta git local para "my_broken_local_repo"
  3. Use "git clone <url_from_1>" para obter uma cópia local nova do repositório remoto do git

Na minha experiência, o Eclipse lida com o mundo mudando muito bem. No entanto, pode ser necessário selecionar projetos afetados no Eclipse e limpá-los para forçar o Eclipse a reconstruí-los. Eu acho que outros IDEs também podem precisar de uma reconstrução forçada.

Um benefício secundário do procedimento acima é que você descobrirá se o seu projeto depende de arquivos locais que não foram colocados no git. Se você achar que estão faltando arquivos, poderá copiá-los de "my_broken_local_repo" e adicioná-los ao git. Depois de ter certeza de que seu novo repositório local tem tudo o que você precisa, é possível excluir "my_broken_local_repo".

Adam Gawne-Cain
fonte
0

Se você quiser apenas jogar fora as confirmações locais e manter as modificações feitas nos arquivos,
git reset @ ~
Outras respostas abordaram a reinicialização completa

Ashish Banker
fonte