Como reverter um repositório Git para uma persistência anterior
Se eu fizer git log
, Então eu recebo o seguinte resultado:
$ 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 a partir de 3 de novembro, ou seja, commit 0d1d7fc
?
30 answers
Mudar temporariamente para outro commit
Se você quer voltar temporariamente para ele, brincar, em seguida, voltar para onde você está, tudo que você tem que 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ê quer fazer commits enquanto estiver lá, faça um novo branch enquanto estiver lá.
git checkout -b old-state 0d1d7fc32
Para voltar para onde estava, verifique o ramo onde estava. (Se você fez mudanças, como sempre quando mudar de ramos, você terá que lidar com eles conforme apropriado. Você poderia reiniciar para jogá-los fora; você poderia esconder, checkout, stash pop para levá-los com você; você poderia enviá-los para um branch lá se você quiser um branch lá.)
Apagar as autorizações não publicadas
Se, por outro lado, queres mesmo livrar-te de tudo o que fizeste desde então, há duas possibilidades. Um, se você não publicou nenhum destes commits, simplesmente reiniciar:# 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 fizeres asneira, já deitaste fora as tuas mudanças locais, mas podes pelo menos voltar ao que eras antes, reiniciando-as de novo.
Anulação de autorizações publicadas com novas autorizações
Por outro lado, se você publicou o trabalho, você provavelmente não quer reiniciar o ramo, já que isso é efetivamente reescrever a história. Nesse caso, poderias reverter os compromissos. Com o Git, o revert tem um significado muito específico: criar um commit com o patch inverso para cancelar. Assim não reescreves nenhuma história.# 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 git-revert
manpage {[28] } na verdade, cobre muito disso na sua descrição. Outro link útil é Este git-scm.com secção sobre o git-revert.
Se decidir que não queria reverter afinal de contas, poderá reverter a reversão (como descrito aqui) ou reiniciar para antes da reversão (veja a secção anterior).
Também pode achar esta resposta útil neste caso.:
como se mover Voltar para um local anterior? (Cabeça solta)
A reverter a cópia de trabalho para o Commit mais recente
Para reverter para uma persistência anterior, ignorando quaisquer alterações:
git reset --hard HEAD
Onde o HEAD é o último commit no seu ramo actual
Reverter a cópia de trabalho para um Commit mais antigo
Voltar a um commit mais antigo do 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 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 questão semelhante de excesso de pilha, reverter para um commit por um hash SHA em Git?.
git revert --no-commit 0766c053..HEAD
git commit
Isto irá reverter tudo da cabeça para o hash do commit, o que significa que irá recriar o estado do commit na árvore de trabalho como se Todos os commits desde então tivessem voltado para trás. Você pode então enviar a árvore atual, e ela irá criar um novo commit essencialmente equivalente ao commit para o qual você "reverteu".
(a bandeira --no-commit
permite ao git reverter todos os commits de uma vez- caso contrário, você será solicitado para uma mensagem para cada commit no intervalo, enchendo o seu histórico com novos commits desnecessários.)
Esta é uma maneira segura e fácil de voltar para um estado anterior . Nenhum histórico é destruído, então ele pode ser usado para commits que já foram tornados públicos.
A melhor opção para mim e provavelmente para outros é a opção git reset:
git reset --hard <commidId> && git clean -f
Esta tem sido a melhor opção para mim! É simples, rápido e eficaz!
Nota : Como mencionado em comentários, não faça isso se você está compartilhando seu ramo com outras pessoas que têm cópias dos antigos commits
Também dos comentários, se quisesse um método menos 'ballzy', poderia usar
git clean -i
First of all what is HEAD?
HEAD
é simplesmente uma referência ao commit atual (último) no ramo atual. Só pode haver um HEAD
em determinado momento (excluindo git worktree
).
O conteúdo de HEAD
é armazenado dentro de .git/HEAD
, e contém os 40 bytes SHA - 1 do commit actual.
detached HEAD
Se não estiver a tomar o último commit-significando que HEAD
está apontando para um commit anterior na história que é chamado detached HEAD
.
Na linha de comandos irá parecer - se com este-SHA-1 em vez do nome do ramo, uma vez que o HEAD
não está a apontar para a ponta do ramo actual:
Algumas opções sobre como recuperar de uma cabeça separada:
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 vai ... obter a nova ramificação que aponta para a persistência desejada. Este comando irá sair para um determinado commit.
Neste ponto você pode criar um ramo e começar a trabalhar a partir deste ponto em:
# 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
Também podes usar o reflog
. git reflog
irá mostrar qualquer alteração que actualize o HEAD
e se verificar o item de reflog desejado, irá voltar a configurar o HEAD
para esta persistência.
Cada vez que a cabeça é modificada haverá uma nova entrada na reflog
git reflog
git checkout HEAD@{...}
Isto vai levá-lo de volta ao seu commit desejado.
git reset HEAD --hard <commit_id>
"Move" a tua 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 ) também pode usar o
git rebase --no-autostash
.
Este esquema ilustra que comando faz o quê. Como você pode ver aqui reset && checkout
modifique o HEAD
.
Se quiser "descompletar", apagar a última mensagem de commit e colocar os ficheiros modificados de novo no staging, irá usar o comando:
git reset --soft HEAD~1
-
--soft
indica que os ficheiros por persistir devem ser conservados como ficheiros de trabalho em vez de--hard
que os rejeitariam. -
HEAD~1
é o último commit. Se quiser reverter 3 commits, pode utilizarHEAD~3
. Se você quiser rollback para um número de revisão específico, você também pode fazer isso usando seu SHA condensado.
Este é um comando extremamente útil em situações em que você cometeu a coisa errada e você quer desfazer esse último commit.
Fonte: http://nakkaya.com/2009/09/24/git-delete-last-commit/
Eu tentei muitas maneiras de reverter as mudanças locais no Git, e parece que isso funciona melhor se você só quiser reverter para o último estado de commit.
git add . && git checkout master -f
Breve descrição:
- não criará nenhum commits como
git revert
faz. - não vai separar a tua cabeça como
git checkout <commithashcode>
faz. - irá anular todas as suas alterações locais e apagar todos os ficheiros adicionados desde a última persistência no ramo. Só funciona com nomes de ramos. pode reverter apenas para o commit mais recente no ramo desta forma.
Encontrei uma maneira muito mais conveniente e simples de alcançar os resultados acima:
git add . && git reset --hard HEAD
Onde a cabeça aponta para o mais recente envio para a sua secção actual.
É o mesmo 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, uma vez que isto é o que a maioria das pessoas esperam que eu acredite quando retornar ao commit mais recente.
Pode fazer isto pelos seguintes dois comandos:
git reset --hard [previous Commit SHA id here]
git push origin [branch Name] -f
Irá remover a sua persistência anterior do Git.
Se quiser manter as suas alterações, também pode utilizar:
git reset --soft [previous Commit SHA id here]
Então ele irá salvar as suas alterações.
Diga que tem os seguintes commits num ficheiro de texto chamado ~/commits-to-revert.txt
(eu usei git log --pretty=oneline
para os Obter)
fe60adeba6436ed8f4cc5f5c0b20df7ac9d93219
0c27ecfdab3cbb08a448659aa61764ad80533a1b
f85007f35a23a7f29fa14b3b47c8b2ef3803d542
e9ec660ba9c06317888f901e3a5ad833d4963283
6a80768d44ccc2107ce410c4e28c7147b382cd8f
9cf6c21f5adfac3732c76c1194bbe6a330fb83e3
fff2336bf8690fbfb2b4890a96549dc58bf548a5
1f7082f3f52880cb49bc37c40531fc478823b4f5
e9b317d36a9d1db88bd34831a32de327244df36a
f6ea0e7208cf22fba17952fb162a01afb26de806
137a681351037a2204f088a8d8f0db6e1f9179ca
Crie um script 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
Isto reverte tudo de volta para o estado anterior, incluindo criações de arquivos e diretórios, e supressões, commit it to your branch e você mantém o histórico, mas você tem ele revertido de volta para a mesma estrutura de arquivos. Porque é que o Git não tem um git revert --to <hash>
está para além de mim.
Alternativas adicionais às soluções de Jefromi
As soluções de Jefromi são definitivamente as melhores, e você deve definitivamente usá-las. No entanto, por uma questão de completude, eu também quis mostrar essas outras soluções alternativas, que também pode ser usado para reverter um commit (no sentido de que você cria um novo commit que anula as alterações anteriores cometer, assim como o que git revert
faz).
git revert
.
Alternativa 1: Resets duros e moles
Esta é uma versão ligeiramente modificada da solução de Charles Bailey para reverter a um commit de um hash SHA em 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 resets suaves irão deixar o estado do commit anterior encenado em o índice/área de estadiamento, que você pode então enviar.
Alternativa 2: apagar a árvore actual e substituir pela nova
Esta solução vem da solução do svick para Checkout antigo commit e torná - lo um novo commit:
git rm -r .
git checkout <commit> .
git commit
Da mesma forma que a alternativa #1, isto reproduz o estado de <commit>
na cópia de trabalho actual. É necessário fazer git rm
Primeiro porque git checkout
não irá remover os ficheiros que foram adicionados desde <commit>
.
Aqui está uma maneira muito mais simples de voltar para um commit anterior (e tê - lo em um estado não recomendado, para fazer com ele o que quiser):
git reset HEAD~1
Então, não há necessidade de IDs de commit e assim por diante:)
OK, voltar ao commit anterior no git é muito fácil...
Reverter para trás sem manter as alterações:
git reset --hard <commit>
Reverta mantendo as alterações:
git reset --soft <commit>
Explique: usando o git reset, você pode reiniciar para um estado específico, é comum usá-lo com um hash de commit como você vê acima.
Mas como você vê a diferença é usar as duas bandeiras --soft
e --hard
, por padrão git reset
Usando --soft
bandeira, mas é uma boa pratique sempre usando a bandeira, eu explico cada bandeira:
--soft
A opção predefinida, tal como foi explicada, não precisa de a indicar, não muda a árvore de trabalho, mas adiciona todos os ficheiros de alterações prontos a persistir, por isso volta ao estado de persistência que muda para os ficheiros que se encontram Desimpedidos.
--hard
Tenha cuidado com esta bandeira, que reinicia a árvore de trabalho e todas as alterações nos ficheiros rastreados e tudo desaparecerá!Também criei a imagem abaixo isso pode acontecer na vida real trabalhando com o git:
Assumindo que estás a falar do mestre e do respectivo ramo (que disse, Este pode ser qualquer ramo de trabalho com o qual estás 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
Encontrei a resposta no blog post apagar o repo Git remoto na persistência específica.
git reset --hard <commit_hash>
git push origin <branch_name> --force
A chave aqui está a forçar o empurrão, sem commits/commit mensagens extra, etc.
Depois de todas as alterações, quando carregar em todos estes comandos, poderá ter de usar:
git push -f ...
E não apenas git push
.
Existe um comando (não uma parte do núcleo Git, mas está no Pacote git-extras) especificamente para reverter e encenar commits antigos:
git back
De acordo com o man page , também pode ser usado como tal:
# Remove the latest three commits
git back 3
Seleccione o commit necessário e verifique-o por
git show HEAD
git show HEAD~1
git show HEAD~2
Até obter o compromisso necessário. Para esclarecer isso, faça
git reset --hard HEAD~1
Ou git reset --hard HEAD~2
ou seja lá o que for.
Reverter para a persistência mais recente e ignorar todas as alterações Locais:
git reset --hard HEAD
Para manter as alterações do commit anterior para HEAD e mover para o commit anterior, faça:
git reset <SHA>
Se não forem necessárias alterações do commit anterior para o HEAD e descartar todas as alterações, faça:
git reset --hard <SHA>
git add -A .
git reset --hard HEAD
Apenas git reset --hard HEAD
vai se livrar de modificações, mas não vai se livrar de arquivos "novos". No caso deles, eles acidentalmente arrastaram uma pasta importante em algum lugar Aleatório, e todos esses arquivos estavam sendo tratados como novos pelo Git, então um reset --hard
não corrigiu isso. Executando o git add -A .
de antemão, ele os rastreou explicitamente com o git, para ser eliminado pelo reset.
Esta é mais uma maneira de reiniciar directamente para um commit recente
git stash
git stash clear
Limpa directamente todas as mudanças que tem vindo a fazer desde o último commit.
PS: tem um pequeno problema; também apaga todas as alterações de stash que guardou recentemente. O que, na maioria dos casos, não deve importar.
git reset --hard origin/master
Https://superuser.com/questions/273172/how-to-reset-master-to-origin-master
Você pode completar todos estes passos iniciais e empurrar de volta para o git repo.
Puxe a versão mais recente do seu repositório de Bitbucket usando o
git pull --all
comando.-
Execute o comando de Registo git com-n 4 do seu terminal. O número após o -n determina o número de commits no log a partir do commit mais recente no seu histórico local.
$ git log -n 4
Repor a cabeça do histórico do seu repositório com o
git reset --hard HEAD~N
onde N é o número de commits você quer levar a cabeça de volta. No exemplo seguinte a cabeça seria ajustado para trás um persistir, até à última persistência no histórico do repositório:Empurre a mudança para o git repo usando
git push --force
para forçar o push alteracao.
Se quiser o repositório git para uma persistência anterior
git pull --all
git reset --hard HEAD~1
git push --force
Reverter é o comando para reverter os commits.
git revert <commit1> <commit2>
Amostra:
git revert 2h3h23233
É capaz de tirar alcance da cabeça como por baixo. Aqui 1 diz " reverter a última persistência."
git revert HEAD~1..HEAD
E depois fazer git push
Se a situação é uma urgente , e você só quer fazer o que o interrogador pediu de uma maneira rápida e suja , assumindo que o seu projecto está sob o directório "o meu projecto":
Copiar o diretório inteiro e chamá-lo de outra coisa, como "meu projeto - cópia"
-
Faça:
git reset --hard [first-4-letters&numbers-of-commit's-SHA]
Depois tem duas versões no seu sistema... você pode examinar ou copiar ou modificar arquivos de interesse, ou o que quer que, a partir do commit anterior. Você pode descartar completamente os arquivos em "my project-copy", se você decidiu que o novo trabalho não ia a lado nenhum...
A coisa óbvia se quiser continuar com o estado do projecto sem De facto descartar o trabalho, dado que este commit obtido é mudar o nome do seu directório de novo: remova o projecto que contém o commit obtido (ou dê - lhe um nome temporário) e renomeie o seu directório "my project-copy" de volta para "my project". Então provavelmente fazer outro commit justo logo.
Git é um brilhante criação, mas você não pode simplesmente "pegar na mosca": também pessoas que tenta explicar demasiadas vezes suponha conhecimento prévio de outros VCS [Sistemas de Controle de Versão] e mergulhar muito muito profundo, muito em breve, e de cometer outros crimes, como o uso de termos intercambiáveis para "conferir" - de forma que, por vezes, aparecem quase calculado para confundir um iniciante.
Para te poupares ao stress, tens de ler um livro sobre o Git. recomenda "controlo de versões com Git" . E se você pode confiar em mim (ou melhor, minhas cicatrizes) quando eu digo "tem que", segue-se que você pode muito bem fazê-lo agora.. Grande parte da complexidade do Git vem de ramificação e, em seguida, remerging. Mas, pela sua pergunta, não há razão para as pessoas o cegarem com a ciência. Especialmente se, por exemplo, esta é uma situação desesperada e você é um novato com Git!PS: outro pensamento: é (agora) na verdade, muito simples de 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 o repositório Git inteiro usando a solução rápida e suja acima. Veja a resposta por Fryer usando -- separate-git-dir aqui. esteja avisado , no entanto: se tiver um repositório de "directório separado" que não copia, e fizer um reset rígido, todas as versões subsequentes ao commit de reset serão perdidas para sempre, a menos que você ter, como você absolutamente deve, regularmente backup de seu repositório, de preferência para a nuvem (por exemplo, Google Drive) entre outros lugares.
Tente reiniciar para o commit desejado -
git reset <COMMIT_ID>
(para verificar a utilização do 'COMMIT_ID'git log
)
Isto irá repor todos os ficheiros alterados em estado não adicionado.
Agora você pode checkout
todos os arquivos não adicionados por
git checkout .
Verifique git log
para verificar as suas alterações.
Actualizar
Se você tem um e apenas commit no seu repo, tente
git update-ref -d HEAD
Primeiro tem de 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 hash commit é EFGHIJK:
git reset --hard EFGHIJK
Por último, empurre desenvolva novamente:
git push origin develop
Se quiser corrigir algum erro na última persistência, uma boa alternativa seria usar o comando git commit --amend. Se o último commit não for apontado por nenhuma referência, isto fará o truque, pois ele cria um commit com o mesmo pai que o último commit. Se não houver nenhuma referência ao último commit, ele simplesmente será descartado e este commit será o último commit. Esta é uma boa maneira de corrigir commits sem reverter commits. No entanto, tem as suas próprias limitações.
Tive um problema semelhante e queria voltar ao Commit anterior. No meu caso, eu não estava intetessed para manter o commit mais novo, Portanto eu useiCuidado! Este comando pode causar a perda do histórico de commit, se o utilizador colocar o commit errado erradamente. Tem sempre apoio extra do teu rabo. onde mais, no caso de cometeres erros, é um pouco mais seguro. :)
Hard
.
Foi assim que fiz:
git reset --hard CommitId && git clean -f
Isto irá reverter no local o repositório, aqui depois de usar o git push -f
irá actualizar o repositório remoto.
git push -f
Primeiro, obter o texto que identifica o commit em alguma data, fazendo:
git rev-list -n 1 --before="2009-07-27 13:37" origin/master
Imprime o identificador de commit, pega no texto (por exemplo, XXXX) e faz:
git checkout XXXX