Como reverto um repositório Git para um commit anterior?

7630

Como reverto do meu estado atual para uma captura instantânea feita em um determinado commit?

Se eu fizer git log, então recebo a seguinte saída:

$ git log
commit a867b4af366350be2e7c21b8de9cc6504678a61b`
Author: Me <[email protected]>
Date:   Thu Nov 4 18:59:41 2010 -0400

blah blah blah...

commit 25eee4caef46ae64aa08e8ab3f988bc917ee1ce4
Author: Me <[email protected]>
Date:   Thu Nov 4 05:13:39 2010 -0400

more blah blah blah...

commit 0766c053c0ea2035e90f504928f8df3c9363b8bd
Author: Me <[email protected]>
Date:   Thu Nov 4 00:55:06 2010 -0400

And yet more blah blah...

commit 0d1d7fc32e5a947fbd92ee598033d85bfc445a50
Author: Me <[email protected]>
Date:   Wed Nov 3 23:56:08 2010 -0400

Yep, more blah blah.

Como reverto para o commit a partir de 3 de novembro, ou seja, commit 0d1d7fc?

Crazy Serb
fonte
116
Aqui está um post muito claro e completo sobre como desfazer coisas no git, direto do Github.
Nobita
3
Relacionado: Reversão para um commit antigo do Git em um repositório público . Observe que essa pergunta adiciona uma restrição de que o repositório seja público.
58
Eu amo o git, mas o fato de haver 35 respostas para algo que deve ser incrivelmente simples expõe um grande problema com o git. Ou são os documentos?
O homem de muffin
2
Como é a linguagem "armadilha" em usar a palavra para reverter como coloquialmente significa redefinir nem mesmo abordada aqui ??? 6594 upvotes até agora e não uma edição dessa maneira, para enfatizar a diferença? Não seria mais confuso para se referir a "salvar um arquivo" aqui com a expressão "cometer" ...
RomainValeri

Respostas:

9732

Isso depende muito do que você quer dizer com "reverter".

Alternar temporariamente para uma confirmação diferente

Se você quiser voltar temporariamente, brincar e voltar para onde está, tudo o que você precisa fazer é verificar o commit desejado:

# This will detach your HEAD, that is, leave you with no branch checked out:
git checkout 0d1d7fc32

Ou, se você quiser fazer confirmações enquanto estiver lá, vá em frente e faça uma nova ramificação enquanto estiver nisso:

git checkout -b old-state 0d1d7fc32

Para voltar para onde você estava, basta verificar o ramo em que estava novamente. (Se você fez alterações, como sempre ao trocar de ramificação, precisará lidar com elas conforme apropriado. Você pode redefinir para jogá-las fora; você pode esconder, fazer check-out, esconder pop para levá-las com você; pode comprometer para uma filial lá, se você quiser uma filial lá.)

Exclusões definitivas confirmadas não publicadas

Se, por outro lado, você realmente deseja se livrar de tudo o que fez desde então, há duas possibilidades. Primeiro, se você não publicou nenhum desses commits, basta redefinir:

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

Se você errar, você já descartou as alterações locais, mas pode pelo menos voltar para onde estava antes, redefinindo novamente.

Desfazer confirmações publicadas com novas confirmações

Por outro lado, se você publicou o trabalho, provavelmente não deseja redefinir a ramificação, pois isso está reescrevendo efetivamente o histórico. Nesse caso, você poderia realmente reverter os commits. Com o Git, revert tem um significado muito específico: crie um commit com o patch reverso para cancelá-lo. Dessa forma, você não reescreve nenhum histórico.

# This will create three separate revert commits:
git revert a867b4af 25eee4ca 0766c053

# It also takes ranges. This will revert the last two commits:
git revert HEAD~2..HEAD

#Similarly, you can revert a range of commits using commit hashes:
git revert a867b4af..0766c053 

# Reverting a merge commit
git revert -m 1 <merge_commit_sha>

# To get just one, you could use `rebase -i` to squash them afterwards
# Or, you could do it manually (be sure to do this at top level of the repo)
# get your index and work tree into the desired state, without changing HEAD:
git checkout 0d1d7fc32 .

# Then commit. Be sure and write a good message describing what you just did
git commit

A página de git-revertmanual realmente cobre muito disso em sua descrição. Outro link útil é esta seção do git-scm.com sobre o git-revert .

Se você decidir que não deseja reverter, afinal, você pode reverter a reversão (conforme descrito aqui) ou redefinir para antes da reversão (consulte a seção anterior).

Você também pode encontrar esta resposta útil neste caso:
Como mover o HEAD de volta para um local anterior? (Cabeça destacada)

Cascabel
fonte
118
@ O comentário de Rod sobre git revert HEAD~3como a melhor maneira de reverter os 3commits é uma convenção importante.
Nova Alexandria
19
Você poderia escrever o número inteiro? como:git reset --hard 0d1d7fc32e5a947fbd92ee598033d85bfc445a50
Spoeken
16
@MathiasMadsenStav Sim, é claro que você pode especificar confirmações pelo SHA1 completo. Usei hashes abreviados para tornar a resposta mais legível, e você também costuma usá-los se estiver digitando. Se você estiver copiando e colando, use o hash completo. Consulte Especificando revisões no man git rev-parse para obter uma descrição completa de como você pode nomear commits.
Cascabel
59
Você pode usar git revert --no-commit hash1 hash2 ...e depois disso apenas comprometer cada revert em um commitgit commit -m "Message"
Mirko Akov
6
O que 'publicar' significa neste contexto?
precisa saber é o seguinte
1852

Muitas respostas complicadas e perigosas aqui, mas é realmente fácil:

git revert --no-commit 0766c053..HEAD
git commit

Isso reverterá tudo, desde o HEAD até o hash de confirmação, o que significa que ele recriará esse estado de confirmação na árvore de trabalho como se todos os commit desde que tivessem voltado. Você pode confirmar a árvore atual e ela criará uma nova confirmação essencialmente equivalente à confirmação para a qual você "reverteu".

(O --no-commitsinalizador permite que o git reverta todas as confirmações de uma só vez; caso contrário, você será solicitado a fornecer uma mensagem para cada confirmação no intervalo, desarrumando seu histórico com novas confirmações desnecessárias.)

Essa é uma maneira fácil e segura de reverter para um estado anterior . Nenhum histórico é destruído, portanto pode ser usado para confirmações que já foram tornadas públicas.

Yarin
fonte
23
Se você realmente deseja ter confirmações individuais (em vez de reverter tudo com uma grande confirmação), pode passar em --no-editvez de --no-commit, para não precisar editar uma mensagem de confirmação para cada reversão.
88
Se uma das confirmações entre 0766c053..HEAD for uma mesclagem, haverá um erro aparecendo (relacionado ao no -m especificado). Isso pode ajudar aqueles que se deparam com isso: stackoverflow.com/questions/5970889/…
timhc22
7
Para ver as diferenças antes de confirmar, use git diff --cached.
19615 John Erck
21
$ git revert --no-commit 53742ae..HEADretornafatal: empty commit set passed
Alex G
10
@AlexG, é porque você precisa digitar o hash antes daquele para o qual deseja voltar. No meu caso, hashes eram como: 81bcc9e HEAD{0}; e475924 HEAD{1}, ...(a partir git reflog), e eu queria desfazer o que eu fiz no 81bcc9e, então eu tinha que fazergit revert e475924..HEAD
EpicPandaForce
1611

Rogue Coder?

Trabalhando por conta própria e só quer que funcione? Siga estas instruções abaixo, elas funcionaram de maneira confiável para mim e para muitas outras por anos.

Trabalhando com outras pessoas? Git é complicado. Leia os comentários abaixo desta resposta antes de fazer algo precipitado.

Revertendo a cópia de trabalho para a confirmação mais recente

Para reverter para uma confirmação anterior, ignorando as alterações:

git reset --hard HEAD

onde HEAD é o último commit em sua filial atual

Revertendo a cópia de trabalho para uma confirmação mais antiga

Para reverter para uma confirmação mais antiga que a confirmação mais recente:

# Resets index to former commit; replace '56e05fced' with your commit code
git reset 56e05fced 

# Moves pointer back to previous HEAD
git reset --soft HEAD@{1}

git commit -m "Revert to 56e05fced"

# Updates working copy to reflect the new commit
git reset --hard

Os créditos vão para uma pergunta semelhante do Stack Overflow, reverter para um commit por um hash SHA no Git? .

boulder_ruby
fonte
33
Fiz isso, mas não consegui confirmar e enviar para o repositório remoto. Eu quero um específico mais velho se comprometer a tornar-se chefe ...
Lennon
7
Isso significa que você já enviou os commits que deseja reverter. Isso pode criar muitos problemas para as pessoas que fizeram check-out do seu código e trabalharam nele. Uma vez que eles não podem aplicar seu commit suavemente sobre o deles. Nesse caso, é melhor reverter o git. Se você é o único a usar o repositório. Faça uma -f git push (Mas pense duas vezes antes de fazer isso)
vinothkr
6
Eu só também quero salientar que, como alternativa para a solução soft reset, em vez de fazer um reset misto primeiro e um hard reset passado, você pode realmente fazer o hard reset primeiro, como segue: git reset --hard 56e05fc; git reset --soft HEAD@{1}; git commit.
5
O @nuton linus, que se autoproclama o criador do git, criticou-o por ser muito complicado. Ele está no registro dizendo que ele estava "chocado" git se tornou tão popular dada a sua complexidade
boulder_ruby
5
@boulder_ruby Acho que você quis dizer Linus Torvalds foi o criador do git. Mas acho que Linus Pauling provavelmente concordaria que o git é complicado.
precisa saber é o seguinte
215

A melhor opção para mim e provavelmente outras é a opção de redefinição do Git:

git reset --hard <commidId> && git clean -f

Esta tem sido a melhor opção para mim! É simples, rápido e eficaz!


** Nota: ** Conforme mencionado nos comentários, não faça isso se você estiver compartilhando seu ramo com outras pessoas que têm cópias dos antigos commit

Também a partir dos comentários, se você quiser um método menos 'ballzy', poderá usar

git clean -i
Pogrindis
fonte
37
Aviso obrigatório: não faça isso se estiver compartilhando sua ramificação com outras pessoas que têm cópias das confirmações antigas, porque usar uma redefinição física como essa os forçará a ressincronizar seu trabalho com a ramificação redefinida recentemente. Para uma solução que explica em detalhes como reverter confirmações com segurança sem perder o trabalho com uma reinicialização completa, consulte esta resposta .
7
Segundo aviso do @ Cupcake ... esteja ciente das consequências. Observe, no entanto, que se sua necessidade é realmente fazer com que essas confirmações desapareçam para sempre, esse método de redefinição + limpeza fará isso e você precisará forçar o envio de suas ramificações modificadas de volta para todo e qualquer controle remoto.
Ashnazg
5
git clean -f PERIGO PERIGO
Tisch
2
Isso define o cabeçalho da minha cópia local para o commit desejado. Mas não consigo fazer alterações porque está atrás do controle remoto. E se eu puxar do controle remoto, ele volta para onde estava o mais tardar na confirmação no ramo remoto. Como oblitero completamente (de todos os lugares) vários commits na minha cópia local que foram enviados?
Ade
2
@Ade .. Você pode usar a git push -fbandeira .. Mas tenha cuidado, ele substituirá o controle remoto .. Certifique-se de saber o que deseja fazer ...
Pogrindis
176

Antes de responder, vamos adicionar alguns antecedentes, explicando o que HEADé isso .

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 HEAD está apontando para um commit anterior no histórico, é chamado detached HEAD.

Digite 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:

Digite 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á o 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 reflog també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

Digite a descrição da imagem aqui


git reset HEAD --hard <commit_id>

"Mova" sua cabeça 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.

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

Digite a descrição da imagem aqui

CodeWizard
fonte
6
Excelente dica para git reflog, isso é exatamente o que eu precisava
smac89
4
Ai! Tudo isso parece muito complicado ... não existe um comando simples que apenas leva um passo para trás no processo? Como ir da versão 1.1 do seu projeto para a versão 1.0? Eu esperaria algo como: stepback_one_commit git ou algo ....
Kokodoko
existe: git reset HEAD^--hard`
CodeWizard
3
@Kokodoko Sim, é terrivelmente complicado ... e um exemplo perfeito de como os especialistas têm pouca consideração pelas pessoas que estão começando. Consulte a minha resposta aqui e também o livro que eu recomendo. Git NÃO é algo que você pode pegar intuitivamente. E posso ter certeza absoluta de que o CodeWizard não fez isso.
mike roedor
145

Se você deseja "descomprimir", apagar a última mensagem de confirmação e colocar os arquivos modificados novamente no teste, você usaria o comando:

git reset --soft HEAD~1
  • --softindica que os arquivos não confirmados devem ser retidos como arquivos de trabalho, ao contrário dos --hardque os descartariam.
  • HEAD~1é o último commit. Se você deseja reverter 3 confirmações, poderá usar HEAD~3. Se você deseja reverter para um número de revisão específico, também poderá fazer isso usando seu hash SHA.

Este é um comando extremamente útil em situações em que você confirmou a coisa errada e deseja desfazer a última confirmação.

Fonte: http://nakkaya.com/2009/09/24/git-delete-last-commit/

Stephen Ostermiller
fonte
3
Isso é suave e gentil: livre de riscos, se você não forçou o seu trabalho
nilsM
124

Você pode fazer isso seguindo os dois comandos a seguir:

git reset --hard [previous Commit SHA id here]
git push origin [branch Name] -f

Isso removerá seu commit anterior do Git.

Se você deseja manter suas alterações, também pode usar:

git reset --soft [previous Commit SHA id here]

Em seguida, ele salvará suas alterações.

Kiran Boghra
fonte
2
Eu tentei 1/2 dúzia de respostas neste post até chegar a este .. todos esses outros, minha configuração do git continuava me dando um erro ao tentar empurrar. Essa resposta funcionou. Obrigado!
Gene Bo
Um detalhe para mim foi que eu perdi as diferenças ... que eu queria manter para ver o que havia feito no commit que não funcionava. Então, da próxima vez que eu iria apenas salvar os dados antes de emitir o comando de reset
Gene Bo
1
Essa foi a única maneira de desfazer uma mesclagem incorreta, a reversão não funcionou nesse caso. Obrigado!
Dave Cole
Melhor resposta. Obrigado
Imran Pollob
Melhor resposta, obrigado.
user1394 2/03
114

Eu tentei várias maneiras de reverter as alterações locais no Git, e parece que isso funciona melhor se você quiser apenas reverter para o estado de confirmação mais recente.

git add . && git checkout master -f

Pequena descrição:

  • NÃO criará nenhum commit como git revertfaz.
  • NÃO destacará sua CABEÇA como git checkout <commithashcode>faz.
  • Ele substituirá todas as alterações locais e DELETE todos os arquivos adicionados desde a última confirmação na ramificação.
  • Ele funciona apenas com nomes de ramificações, portanto, você pode reverter apenas para a confirmação mais recente na ramificação dessa maneira.

Encontrei uma maneira muito mais conveniente e simples de obter os resultados acima:

git add . && git reset --hard HEAD

onde HEAD aponta para a confirmação mais recente na filial atual.

É o mesmo código de código sugerido pelo boulder_ruby, mas eu adicionei git add .antes git reset --hard HEADpara apagar todos os novos arquivos criados desde o último commit, já que é isso que a maioria das pessoas espera que eu acredite ao reverter para o commit mais recente.

Roman Minenok
fonte
83

OK, voltar para um commit anterior no Git é bastante fácil ...

Reverta sem manter as alterações:

git reset --hard <commit>

Reverta mantendo as alterações:

git reset --soft <commit>

Explicação: usando git reset, você pode redefinir para um estado específico. É comum usá-lo com um hash de confirmação, como você vê acima.

Mas como você vê a diferença é usar os dois sinalizadores --softe --hard, por padrão, git resetusar o --softsinalizador, mas é uma boa prática sempre usar o sinalizador, explico cada sinalizador:


--suave

O sinalizador padrão, conforme explicado, não precisa fornecê-lo, não altera a árvore de trabalho, mas adiciona todos os arquivos alterados prontos para confirmação, para que você volte ao status de confirmação, que muda para os arquivos que ficam sem estágio.


--Difícil

Tenha cuidado com esta bandeira. Ele redefine a árvore de trabalho e todas as alterações nos arquivos rastreados e tudo desaparece!


Também criei a imagem abaixo que pode acontecer na vida real trabalhando com o Git:

Git redefinido para uma confirmação

Alireza
fonte
O padrão de git reseté git reset --mixed, não git reset --soft. Por favor, verifique Qual é a diferença entre git reset --mixed, --soft e --hard? e Em inglês simples, o que o “git reset” faz?
Fabio diz Reinstate Monica em
70

Supondo que você esteja falando sobre o mestre e sobre o respectivo ramo (dito isso, pode ser qualquer ramo que você esteja preocupado):

# Reset local master branch to November 3rd commit ID
git reset --hard 0d1d7fc32e5a947fbd92ee598033d85bfc445a50

# Reset remote master branch to November 3rd commit ID
git push -f origin 0d1d7fc32e5a947fbd92ee598033d85bfc445a50:master

Encontrei a resposta em uma postagem de blog (agora não existe mais)

Observe que isso está redefinindo e forçando a alteração no controle remoto, para que, se outros membros de sua equipe já tiverem puxado, você causará problemas para eles. Você está destruindo o histórico de alterações, que é uma razão importante pela qual as pessoas usam o git em primeiro lugar.

Melhor usar reverter (ver outras respostas) do que redefinir. Se você é uma equipe de um homem, provavelmente não importa.

markreyes
fonte
6
Como essa resposta é diferente da miríade de outras pessoas?
Matsmath 10/05
Isso é lamentável. Enviei um email ao blogueiro - espero que ele ainda o tenha!
markreyes
2
A sintaxe push está ausente na maioria das outras sugestões de como corrigir isso. Trabalhou muito bem.
jpa57
61

Digamos que você tenha os seguintes commits em um arquivo de texto chamado ~/commits-to-revert.txt(eu costumava git log --pretty=onelineobtê-los)

fe60adeba6436ed8f4cc5f5c0b20df7ac9d93219
0c27ecfdab3cbb08a448659aa61764ad80533a1b
f85007f35a23a7f29fa14b3b47c8b2ef3803d542
e9ec660ba9c06317888f901e3a5ad833d4963283
6a80768d44ccc2107ce410c4e28c7147b382cd8f
9cf6c21f5adfac3732c76c1194bbe6a330fb83e3
fff2336bf8690fbfb2b4890a96549dc58bf548a5
1f7082f3f52880cb49bc37c40531fc478823b4f5
e9b317d36a9d1db88bd34831a32de327244df36a
f6ea0e7208cf22fba17952fb162a01afb26de806
137a681351037a2204f088a8d8f0db6e1f9179ca

Crie um script de shell Bash para reverter cada um deles:

#!/bin/bash
cd /path/to/working/copy
for i in `cat ~/commits-to-revert.txt`
do
    git revert $i --no-commit
done

Isso reverte tudo de volta ao estado anterior, incluindo criações e exclusões de arquivos e diretórios, e submete-o à sua ramificação e você mantém o histórico, mas você o reverte para a mesma estrutura de arquivo. Por que o Git não tem um git revert --to <hash>está além de mim.

Lance Caraccioli
fonte
41
Você pode fazer um git revert HEAD~3para remover os últimos 3 commits #
187 Rod Rod
25
@ Rod - Não, isso não está certo. Esse comando reverterá o commit que é o terceiro avô do HEAD (não os três últimos commits).
precisa saber é o seguinte
1
@kflorence Ok, obrigado pela informação. Funcionaria git revert -n master~3..master~1? (Como visto em kernel.org/pub/software/scm/git/docs/git-revert.html )
Rod
3
@ Rod - Isso parece certo, com certeza é uma sintaxe feia, não é? Sempre achei o check-out do commit para o qual quero "reverter" e, em seguida, o cometimento mais intuitivo.
Kflorence #
7
Existe uma maneira muito mais fácil de fazer isso agora do que com um script como este, basta usar git revert --no-commit <start>..<end>, porque git revertaceita um intervalo de confirmação em novas (ou todas?) Versões do Git. Observe que o início do intervalo não está incluído na reversão.
58

Alternativas extras às soluções da Jefromi

As soluções da Jefromi são definitivamente as melhores e você deve usá-las definitivamente. No entanto, por uma questão de integridade, eu também queria mostrar essas outras soluções alternativas que também podem ser usadas para reverter uma confirmação (no sentido em que você cria uma nova confirmação que desfaz alterações na confirmação anterior , exatamente como o git revertfaz).

Para ser claro, essas alternativas não são a melhor maneira de reverter confirmações , são as soluções da Jefromi , mas eu só quero ressaltar que você também pode usar esses outros métodos para obter a mesma coisa que git revert.

Alternativa 1: redefinições rígidas e flexíveis

Esta é uma versão ligeiramente modificada da solução de Charles Bailey para reverter para um commit por um hash SHA no Git? :

# Reset the index to the desired commit
git reset --hard <commit>

# Move the branch pointer back to the previous HEAD
git reset --soft HEAD@{1}

# Commit the changes
git commit -m "Revert to <commit>"

Isso basicamente funciona usando o fato de que as redefinições flexíveis deixarão o estado da consolidação anterior em estágios na área de índice / preparação, que você poderá confirmar.

Alternativa 2: Excluir a árvore atual e substituir pela nova

Esta solução vem da solução svick para o commit antigo do Checkout e o torna um novo commit :

git rm -r .
git checkout <commit> .
git commit

Da mesma forma que a alternativa nº 1, isso reproduz o estado da <commit>cópia de trabalho atual. É necessário fazer git rmprimeiro, porque git checkoutnão removerá os arquivos que foram adicionados desde então <commit>.

user456814
fonte
Sobre a Alternativa 1, uma pergunta rápida: ao fazer isso, não perdemos entre os commits, certo?
Bogac
2
@ Bogac - os pontos indicam um caminho de arquivo, neste caso, o diretório atual, portanto, assume-se que você o esteja executando a partir da raiz da sua cópia de trabalho.
Tom
O aviso é repetido várias vezes na resposta, mas alguém poderia acrescentar por que essa não é a melhor maneira - em comparação, com algo parecido git revert HEAD~2..HEADcom a solução vinculada da @ Cascabel (@ Jefromi). Não estou vendo o problema.
Joshua Goldberg
55

Aqui está uma maneira muito mais simples de voltar a um commit anterior (e colocá-lo em um estado não confirmado, para fazer o que você quiser):

git reset HEAD~1

Portanto, não há necessidade de confirmar IDs e assim por diante :)

Paul Walczewski
fonte
não funcionou, um git pull após isso gera: erro: Suas alterações locais nos seguintes arquivos seriam substituídas por mesclagem:
malhal 5/16
1
@malhal Isso é porque você teve alterações não confirmadas. Esconder / redefini-los e, em seguida, ele funcionará sem esse erro.
Paul Walczewski
39

Existe um comando (que não faz parte do núcleo do Git, mas está no pacote git-extras ) especificamente para reverter e preparar os antigos commit:

git back

Pela página do manual , também pode ser usado como tal:

# Remove the latest three commits
git back 3
Homem sombra
fonte
38

A melhor maneira é:

git reset --hard <commidId> && git push --force

Isso redefinirá a ramificação para o commit específico e fará o upload do servidor remoto com os mesmos commit que você fez no local (isso elimina completamente os comandos após o commit específico)

Tenha cuidado, --forcepois o sinalizador remove todas as confirmações subsequentes após a confirmação selecionada, sem a opção de recuperá-las.

david.t_92
fonte
3
funcionou como charme!
Gaurav Gupta 27/02
I downvoted porque eu não consigo ver como a sua resposta fornece qualquer nova informação não já dada em, por exemplo stackoverflow.com/a/37145089/1723886 , stackoverflow.com/a/27438379/1723886 ou stackoverflow.com/a/48756719/1723886 . De fato, a maioria dos commits já menciona git reset --hard, e muitos outros mencionam o uso de --force ou -f para empurrar.
Alex Telon 24/03
Ele faz o trabalho com apenas um comando, claro e simples. Você é livre de votar na minha resposta se não gostar.
david.t_92 26/03
1
Outra opção a considerar no futuro é sugerir uma edição em uma resposta anterior ou adicionar um comentário dizendo que 'isso também pode ser feito em uma linha usando &&', por exemplo. Dessa forma, todos poderão ver a resposta aprimorada em um só lugar.
Alex Telon 27/03
36

Após todas as alterações, quando você pressiona todos esses comandos, pode ser necessário usar:

git push -f ...

E não somente git push.

sivi
fonte
15
Aviso obrigatório: não faça isso se estiver compartilhando seu ramo com outras pessoas que têm cópias dos antigos commit, porque usar um push forçado como esse os forçará a ressincronizar seu trabalho. Para uma solução que explica em detalhes como reverter com segurança as confirmações sem perder o trabalho com um empurrão, consulte esta resposta .
3
Às vezes é isso que você quer. Exemplo: confirmado e enviado várias confirmações para a ramificação errada (ramificação A). Depois de escolher a ramificação B, desejo que essas confirmações sejam removidas da ramificação A. Eu não gostaria de reverter, pois a reversão será aplicada mais tarde quando as ramificações A e B forem mescladas. Fazendo uma redefinição --hard <commitId> na ramificação A seguida por um empurrão forçado remove essas confirmações da ramificação enquanto as preserva na ramificação B. Posso me safar disso porque sei que mais ninguém está desenvolvendo na ramificação A.
Doug R
Obrigado! Eu não conseguia descobrir como fazer o ramo remoto corresponder ao meu ramo local, só precisava fazer um empurrão forçado.
Mido
32

Você pode concluir todas essas etapas iniciais e retornar ao repositório Git.

  1. Puxe a versão mais recente do seu repositório do Bitbucket usando o git pull --allcomando

  2. Execute o comando Git log -n 4do seu terminal. O número após o -ndetermina o número de confirmações no log a partir da confirmação mais recente em seu histórico local.

    $ git log -n 4
    
  3. Redefina o cabeçalho do histórico do seu repositório usando git reset --hard HEAD~Nonde N é o número de confirmações que você deseja recuperar. No exemplo a seguir, o cabeçalho seria atrasado em uma confirmação, até a última confirmação no histórico do repositório:

  4. Envie a alteração para o repositório Git usando git push --forcepara forçar a alteração.

Se você deseja que o repositório Git tenha um commit anterior:

git pull --all
git reset --hard HEAD~1
git push --force
Nanhe Kumar
fonte
30

Reverta para a confirmação mais recente e ignore todas as alterações locais:

git reset --hard HEAD
Mohammed Irfan Tirupattur
fonte
28

Selecione o commit necessário e verifique-o

git show HEAD
git show HEAD~1
git show HEAD~2 

até obter a confirmação necessária. Para fazer o HEAD apontar para isso, faça

git reset --hard HEAD~1

ou git reset --hard HEAD~2ou o que seja.

tonythomas01
fonte
7
Aviso obrigatório: não faça isso se estiver compartilhando sua ramificação com outras pessoas que têm cópias das confirmações antigas, porque usar uma redefinição física como essa os forçará a ressincronizar seu trabalho com a ramificação redefinida recentemente. Para uma solução que explica em detalhes como reverter confirmações com segurança sem perder o trabalho com uma reinicialização completa, consulte esta resposta .
2
Além disso, para ser claro, git show HEADé equivalente a apenas usar git log HEAD -1.
25

Se a situação for urgente e você quiser fazer o que o interlocutor pediu de maneira rápida e suja , supondo que seu projeto esteja em um diretório chamado, por exemplo, "meu projeto":


RÁPIDO E SUJO : dependendo das circunstâncias, rápido e sujo podem, de fato, ser MUITO BOM. O que minha solução aqui faz NÃO substitui irreversivelmente os arquivos que você possui em seu diretório de trabalho por arquivos arrastados / extraídos das profundezas do repositório git à espreita sob seu diretório .git / usando comandos git incrivelmente inteligentes e diabolicamente poderosos, dos quais existem muitos. VOCÊ NÃO TEM QUE MERGULHAR NO MAR PROFUNDO PARA RECUPERAR o que pode parecer uma situação desastrosa, e tentar fazê-lo sem experiência suficiente pode ser fatal .


  1. Copie o diretório inteiro e chame-o de outra coisa, como "meu projeto - copiar". Supondo que os arquivos do seu repositório git ("repo") estejam no diretório "meu projeto" (o local padrão para eles, em um diretório chamado ".git"), você agora terá copiado os arquivos de trabalho e os arquivos de repo.

  2. Faça isso no diretório "meu projeto":

    .../my project $ git reset --hard [first-4-letters&numbers-of-commit's-SHA]
    

Isso retornará o estado do repositório em "meu projeto" para o que era quando você fez esse commit (um "commit" significa uma captura instantânea de seus arquivos de trabalho). Todas as confirmações desde então serão perdidas para sempre em "meu projeto", MAS ... elas ainda estarão presentes no repositório em "meu projeto - cópia", uma vez que você copiou todos esses arquivos - incluindo os de ... /. Git /.

Você tem duas versões em seu sistema ... você pode examinar ou copiar ou modificar arquivos de interesse, ou o que for, da confirmação anterior. Você pode descartar completamente os arquivos em "meu projeto - copiar", se tiver decidido o novo trabalho desde que a confirmação restaurada não chegaria a lugar algum ...

O óbvio se você deseja continuar com o estado do projeto sem realmente descartar o trabalho, pois esse commit recuperado é renomear seu diretório novamente: exclua o projeto que contém o commit recuperado (ou atribua um nome temporário) e renomeie seu " meu projeto - copie o diretório "de volta para" meu projeto ". Então talvez tente entender algumas das outras respostas aqui e provavelmente faça outro commit logo.

O Git é uma criação brilhante, mas absolutamente ninguém é capaz de "buscá-lo rapidamente": também pessoas que tentam explicar isso com muita frequência assumem o conhecimento prévio de outros VCS [Version Control Systems] e se aprofundam demais. cedo demais e cometer outros crimes, como usar termos intercambiáveis ​​para "fazer check-out" - de maneiras que às vezes parecem quase calculadas para confundir um iniciante.

Para economizar muito estresse, aprenda com minhas cicatrizes. Você precisa praticamente ler um livro sobre o Git - eu recomendaria "Version Control with Git" . Faça isso mais cedo ou mais tarde. Se o fizer, lembre-se de que grande parte da complexidade do Git vem da ramificação e remessa: você pode pular essas partes em qualquer livro. Da sua pergunta, não há razão para que as pessoas te ceguem com a ciência .

Especialmente se, por exemplo, esta é uma situação desesperadora e você é um novato no Git!

PS: Outro pensamento: agora é bastante simples manter o repositório Git em um diretório diferente daquele com os arquivos de trabalho. Isso significa que você não precisaria copiar todo o repositório Git usando a solução rápida e suja acima. Veja a resposta de Fryer usando --separate-git-dir aqui . Entretanto, esteja avisado : se você tiver um repositório de "diretório separado" que não copia e fizer uma reinicialização completa, todas as versões subseqüentes à confirmação de redefinição serão perdidas para sempre, a menos que você tenha, como absolutamente deveria, faça backup regularmente do seu repositório, de preferência para a nuvem (por exemplo, Google Drive ), entre outros lugares.

Nesse assunto de "fazer backup na nuvem", o próximo passo é abrir uma conta (é claro) com o GitHub ou (melhor na minha opinião) com o GitLab . Em seguida, você pode git pushexecutar regularmente um comando para atualizar seu repositório na nuvem "corretamente". Mas, novamente, falar sobre isso pode ser muito cedo.

microfone roedor
fonte
23

Esta é mais uma maneira de redefinir diretamente para uma confirmação recente

git stash
git stash clear

Ele limpa diretamente todas as alterações que você está fazendo desde o último commit.

PS: Tem um pequeno problema; ele também exclui todas as alterações de stash armazenadas recentemente. O que eu acho que na maioria dos casos não deve importar.

Redes de pontos
fonte
NOTA: Novos arquivos não adicionados ao índice não são escondidos. Você também pode adicioná-los ou excluí-los manualmente.
andreyro
Por que, oh, por que limpar o estoque? Além de não ser uma solução, isso é realmente prejudicial. A leitura da primeira frase da pergunta invalida imediatamente a solução stash (que pode ser útil SOMENTE para redefinir o LAST commit).
RomainValeri 7/03/19
22

Para limpar completamente o diretório de um codificador de algumas alterações acidentais, usamos:

git add -A .
git reset --hard HEAD

Apenas git reset --hard HEADse livrará de modificações, mas não se livrará de arquivos "novos". No caso deles, eles arrastaram acidentalmente uma pasta importante para algum lugar aleatório, e todos esses arquivos estavam sendo tratados como novos pelo Git, para reset --hardnão corrigi-lo. Ao executar o git add -A .antemão, ele rastreou explicitamente todos eles com git, a serem eliminados pela redefinição.

Chris Moschini
fonte
21

Para manter as alterações do commit anterior no HEAD e passar para o commit anterior, faça:

git reset <SHA>

Se não forem necessárias alterações da confirmação anterior para HEAD e apenas descartar todas as alterações, faça:

git reset --hard <SHA>
Vishnu Atrai
fonte
20

Acredito que algumas pessoas possam chegar a essa pergunta querendo saber como reverter as alterações confirmadas que fizeram em seu mestre - ou seja, jogue tudo fora e volte à origem / mestre, nesse caso, faça o seguinte:

git reset --hard origin/master

/superuser/273172/how-to-reset-master-to-origin-master

nevster
fonte
18

Reverter é o comando para reverter as confirmações.

git revert <commit1> <commit2> 

Amostra:

git revert 2h3h23233

É capaz de variar desde a CABEÇA como abaixo. Aqui 1 diz "reverter o último commit".

git revert HEAD~1..HEAD

e então faça git push

Sireesh Yarlagadda
fonte
14

Tente redefinir para o commit desejado -

git reset <COMMIT_ID>

(para verificar COMMIT_ID, use git log )

Isso redefinirá todos os arquivos alterados para o estado não adicionado.

Agora você pode checkouttodos os arquivos não adicionados por

git checkout .

Marque git logpara verificar suas alterações.

ATUALIZAR

Se você tem um único compromisso no seu repositório, tente

git update-ref -d HEAD

optimistanoop
fonte
13

Como suas confirmações são enviadas remotamente, você precisa removê-las. Deixe-me supor que seu ramo está se desenvolvendo e é empurrado sobre a origem .

Você primeiro precisa remover o desenvolvimento da origem :

git push origin :develop (note the colon)

Então você precisa desenvolver o status que deseja, deixe-me assumir que o hash de confirmação é EFGHIJK:

git reset --hard EFGHIJK

Por fim, pressione desenvolver novamente:

git push origin develop
George Ninan
fonte
13

Cuidado! Este comando pode causar a perda do histórico de confirmação, se o usuário colocar o commit errado por engano. Sempre tenha um backup extra do seu git em algum outro lugar, caso você cometa erros, pois você é um pouco mais seguro. :)

Eu tive um problema semelhante e queria voltar a um commit anterior. No meu caso, eu não estava interessado em manter o commit mais recente, portanto usei Hard.

Foi assim que eu fiz:

git reset --hard CommitId && git clean -f

Isso reverterá no repositório local e, após o uso git push -f, atualizará o repositório remoto.

git push -f
maytham-ɯɐɥʇʎɐɯ
fonte
13

No GitKraken, você pode fazer isso:

  1. Clique com o botão direito do mouse no commit que deseja redefinir e escolha: Redefinir para este commit / Hard :

    Digite a descrição da imagem aqui

  2. Clique com o botão direito do mouse no commit novamente, escolha: Nome do ramo atual / Push :

    Digite a descrição da imagem aqui

  3. Clique no Force Push :

    Digite a descrição da imagem aqui

Obs. : Você precisa ter cuidado, pois todo o histórico de consolidação após a reinicialização forçada é perdido e essa ação é irreversível. Você precisa ter certeza do que está fazendo.

Ângelo Polotto
fonte
11

Se você deseja corrigir algum erro no último commit, uma boa alternativa seria usar o comando git commit --amend . Se o último commit não for apontado por nenhuma referência, isso funcionará, pois ele cria um commit com o mesmo pai que o último commit. Se não houver referência ao último commit, ele será simplesmente descartado e esse commit será o último commit. Essa é uma boa maneira de corrigir confirmações sem revertê-las. No entanto, tem suas próprias limitações.

Upul Doluweera
fonte