voltar Como reverter um repositório Git para um commit anterior




remover commit github (24)

Eu tentei muitas maneiras de reverter as mudanças locais no Git, e parece que isso funciona melhor se você quiser apenas reverter para o último estado de confirmação.

git add . && git checkout master -f

Pequena descrição:

  • NÃO irá criar nenhum commit como git revert faz.
  • NÃO irá desanexar o seu HEAD como o git checkout <commithashcode> .
  • Substituirá todas as alterações locais e EXCLUIR todos os arquivos adicionados desde o último commit na ramificação.
  • Ele funciona apenas com nomes de ramificações, portanto, você pode reverter apenas para o commit mais recente no branch dessa maneira.

Eu encontrei uma maneira muito mais simples e conveniente de alcançar os resultados acima:

git add . && git reset --hard HEAD

onde HEAD aponta para o commit mais recente em sua filial atual.

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

Como eu reverti do meu estado atual para um instantâneo feito em um certo commit?

Se eu fizer git log , então eu 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 reverter para o commit de 3 de novembro, ou seja, commit 0d1d7fc ?


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

Para reverter para um commit anterior, ignorando quaisquer 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 um commit mais antigo que o commit 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 [email protected]{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 , Reverter para um commit por um hash SHA no Git? .


Esta é mais uma maneira de redefinir diretamente para um commit recente

git stash
git stash clear

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

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


A melhor opção para mim e provavelmente para os outros é a opção de reset do Git:

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

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

Observação: conforme mencionado nos comentários, não faça isso se você estiver compartilhando sua filial com outras pessoas que tenham cópias dos commits antigos.

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

git clean -i


OK, voltar ao commit anterior no git é bem fácil ...

Reverta sem manter as alterações:

git reset --hard <commit>

Reverta com as alterações:

git reset --soft <commit>

Explique: usando o 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 está usando as duas flags --soft e --hard , por padrão git reset usando --soft flag, mas é uma boa prática sempre usando o flag, eu explico cada flags:

--suave

O sinalizador padrão, conforme explicado, não precisa fornecê-lo, não altera a árvore de trabalho, mas inclui todos os arquivos de alterações prontos para serem confirmados, portanto, você retorna ao status de confirmação, que altera os arquivos para serem desfeitos.

--Difícil

Tenha cuidado com esse sinalizador, ele redefine a árvore de trabalho e todas as alterações nos arquivos rastreados e todas desaparecerão!

Eu também criei a imagem abaixo que pode acontecer em uma vida real trabalhando com o git:


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

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

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

Eu encontrei a resposta de no post do blog Excluir reit Git remoto para commit específico .


Como seus commits são enviados remotamente, você precisa removê-los. Deixe-me supor que sua ramificação está desenvolvida e é empurrada sobre a origem.

Você primeiro precisa remover o desenvolvimento da origem:

git push origin :develop (note the colon)

Então você precisa se desenvolver para o status que você quer, deixe-me assumir que o commit hash é EFGHIJK:

git reset --hard EFGHIJK

Por último, empurre desenvolver novamente:

git push origin develop

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

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

Isso reverterá tudo, do HEAD de volta ao hash de commit, o que significa que ele irá recriar o estado de commit na árvore de trabalho como se todo commit tivesse sido retornado. Você pode, então, confirmar a árvore atual e criar um novo commit essencialmente equivalente ao commit para o qual você "reverteu".

(O sinalizador --no-commit permite que o git reverta todos os commits de uma só vez - caso contrário, você será solicitado a enviar uma mensagem para cada commit no intervalo, sujando seu histórico com novos commits desnecessários.)

Esta é uma maneira segura e fácil de reverter para um estado anterior . Nenhum histórico é destruído, portanto, ele pode ser usado para commits que já foram tornados públicos.


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

git reset HEAD~1

Então, não há necessidade de cometer ids e assim por diante :)


Antes de responder, vamos adicionar alguns detalhes explicando o que é esse HEAD .

First of all what is HEAD?

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

O conteúdo do HEAD é armazenado dentro de .git/HEAD e contém os 40 bytes SHA-1 do commit atual.

detached HEAD

Se você não está no commit mais recente - o que significa que o HEAD está apontando para um commit anterior no histórico, ele é chamado detached HEAD .

Na linha de comando, ficará assim - SHA-1 em vez do nome da ramificação, pois o HEAD não está apontando para a ponta da ramificação atual:

Algumas opções sobre como se recuperar de uma HEAD desconectada:

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

Isto irá verificar o novo ramo apontando para o commit desejado. Este comando fará o checkout para um determinado commit.

Neste 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 reflog exibirá qualquer mudança que atualizou o HEAD e o check out da entrada do reflog desejado irá definir o HEAD volta para este commit.

Toda vez que o HEAD é modificado, haverá uma nova entrada no reflog

git reflog
git checkout [email protected]{...}

Isso fará com que você volte ao seu compromisso desejado

git reset HEAD --hard <commit_id>

"Mova" sua cabeça 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 usar o git rebase --no-autostash também.

Este esquema ilustra qual comando faz o quê. Como você pode ver, reset && checkout modifique o HEAD .



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

git reset --hard HEAD

Cuidado! Esse comando pode causar perda de histórico de confirmação, se o usuário colocar o commit errado por engano. Tenha sempre um backup extra do seu git em algum outro lugar apenas no caso de você cometer erros, do que você está um pouco mais seguro. :)

Eu tive problema semelhante e queria reverter para Commit anterior. No meu caso, eu não estava intencionado para manter o novo commit, portanto, eu usei Hard.

Foi assim que eu fiz:

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

Isto irá reverter no repositório local, aqui depois de usar git push -firá atualizar o repositório remoto.

git push -f

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

Mudar temporariamente para um commit diferente

Se você quiser voltar temporariamente para ele, brincar e voltar para onde você 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 commits enquanto estiver lá, vá em frente e faça um novo branch enquanto estiver fazendo isso:

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 alternar as ramificações, você terá que lidar com elas conforme apropriado. Você pode redefinir para jogá-las fora; você pode armazenar, fazer check-out, ocultar pop para levá-las com você; eles para um ramo lá se você quiser um ramo lá.)

Hard delete commits não publicados

Se, por outro lado, você quer realmente se livrar de tudo que fez desde então, existem duas possibilidades. Um, se você não publicou nenhum desses commits, simplesmente redefina:

# 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á jogou fora suas alterações locais, mas pode pelo menos voltar para onde estava antes, redefinindo novamente.

Desfazer commits publicados com novos commits

Por outro lado, se você publicou o trabalho, provavelmente não deseja redefinir o ramo, pois isso está efetivamente reescrevendo o histórico. Nesse caso, você poderia de fato reverter os commits. Com o Git, revert tem um significado muito específico: crie um commit com o patch reverso para cancelá-lo. Desta 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 manpage git-revert realmente cobre muito disso em sua descrição. Outro link útil é a seção git-scm.com discutindo git-revert .

Se você decidir que não quer reverter, você pode reverter a reversão (como descrito aqui) ou voltar para antes da reversão (veja a seção anterior).

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


Reverter é o comando para reverter os commits.

git revert <commit1> <commit2> 

Amostra:

git revert 2h3h23233

É capaz de tirar alcance do HEAD como abaixo. Aqui 1 diz "reverter último commit".

git revert HEAD~1..HEAD

e depois fazer git push


Nada aqui funcionou para mim além dessa combinação exata:

git reset --hard <commit_hash>
git push origin <branch_name> --force

A chave aqui é forçar o push, sem commits / commits adicionais, etc.


Existe um comando (não uma parte do Git principal, mas está no pacote git-extras ) especificamente para reverter e testar commits antigos:

git back

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

# Remove the latest three commits
git back 3

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

git add -A .
git reset --hard HEAD

git reset --hard HEADvai se livrar de modificações, mas não vai se livrar de "novos" arquivos. No caso deles, eles acidentalmente arrastaram uma pasta importante para algum lugar aleatório, e todos esses arquivos estavam sendo tratados como novos pelo Git, então reset --hardnão foi resolvido. Ao executar o git add -A .anterior, ele rastreou explicitamente todos eles com o git, para ser eliminado pelo reset.


Se você deseja "descomentar", apagar a última mensagem de confirmação e colocar os arquivos modificados novamente no armazenamento temporário, use o comando:

git reset --soft HEAD~1
  • --soft indica que os arquivos não confirmados devem ser mantidos como arquivos de trabalho opostos a --hard que os descartariam.
  • HEAD~1 é o último commit. Se você quiser reverter 3 commits, você pode usar HEAD~3 . Se você quiser 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ê cometeu a coisa errada e deseja desfazer o último commit.

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


Para reversão (ou para reverter):

  1. git revert --no-commit "commit-code-to-remove" HEAD (por exemplo, git revert --no-commit d57a39dHead)
  2. git commit
  3. git push

Tente acima de dois passos, e se você achar que é isso que você quer, então git push.

Se você encontrar algo errado, faça:

git revert --abort


Alternativas Extra para as Soluções da Jefromi

As soluções da Jefromi são definitivamente as melhores, e você definitivamente deveria usá-las. No entanto, por questão de completude, eu também queria mostrar essas outras soluções alternativas que também podem ser usadas para reverter um commit (no sentido de que você cria um novo commit que desfaz mudanças no commit anterior , assim como o git revert faz) .

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

Alternativa 1: redefinições rígidas e suaves

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 [email protected]{1}

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

Isso basicamente funciona usando o fato de que resets soft deixarão o estado do commit anterior testado na área de índice / staging, que você pode então confirmar.

Alternativa 2: Excluir a Árvore Atual e Substituir pela Nova

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

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

Similarmente à alternativa # 1, isso reproduz o estado de <commit> na cópia de trabalho atual. É necessário fazer git rm primeiro porque o git checkout não irá remover arquivos que foram adicionados desde <commit> .


Se a situação é urgente , basta fazer o que o questionador fez de maneira rápida e suja , assumindo que seu projeto está no diretório "meu projeto":

  1. Copie todo o diretório e chame de outra coisa, como "meu projeto - copiar"

  2. Faz:

    git reset --hard [first-4-letters&numbers-of-commit's-SHA]
    

Você então tem duas versões em seu sistema ... você pode examinar ou copiar ou modificar arquivos de interesse, ou o que quer, do commit anterior. Você pode descartar completamente os arquivos em "meu projeto - cópia", se você decidiu que o novo trabalho estava indo a lugar nenhum ...

O mais óbvio é se você quiser continuar com o estado do projeto sem descartar o trabalho, já que esse commit recuperado é renomear seu diretório novamente: Apague o projeto que contém o commit recuperado (ou dê um nome temporário) e renomeie o seu " meu projeto - copie "diretório de volta para" meu projeto ". Então, provavelmente, faça outro commit em breve.

Git é uma criação brilhante, mas você não pode simplesmente "pegar em tempo real": também as pessoas que tentam explicá-lo com muita freqüência assumem conhecimento prévio de outros VCS [Sistemas de Controle de Versão] e se aprofundam muito profundamente muito cedo, e cometer outros crimes, como usar termos intercambiáveis ​​para "check-out" - de formas que às vezes parecem quase calculadas para confundir um iniciante.

Para poupar muito estresse você tem que praticamente ler um livro sobre o Git - eu recomendaria o "Version Control with Git" . E se você pode confiar em mim (ou melhor, minhas cicatrizes) quando digo "tenho que", segue-se que você também pode fazê-lo agora . Grande parte da complexidade do Git vem da ramificação e, depois, da remineração. Mas a partir da sua pergunta, não há motivo para as pessoas estarem cegando você com a ciência .

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

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


Depois de todas as alterações, quando você pressiona todos esses comandos, talvez seja necessário usar:

git push -f ...

E não apenas git push .


Você pode completar todos os passos iniciais e voltar ao git repo.

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

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

    $ git log -n 4

  3. Redefina a cabeça do histórico do seu repositório usando o git reset --hard HEAD~Nonde N é o número de commits que você quer levar a cabeça para trás. No exemplo a seguir, o cabeçalho seria retrocedido em um commit, para o último commit no histórico do repositório:

  4. Empurre a mudança para git repo usando git push --forcepara forçar a mudança.

Se você quiser o repositório git para um commit anterior

git pull --all
git reset --hard HEAD~1
git push --force




git-revert