Git - Desfazer confirmações enviadas

609

Eu tenho um projeto em um repositório remoto, sincronizado com um repositório local (desenvolvimento) e o servidor (prod). Eu tenho feito algumas alterações confirmadas já enviadas para remoto e extraídas do servidor. Agora, quero desfazer essas alterações. Então, eu poderia apenas git checkoutconfirmar antes das alterações e confirmar as novas, mas acho que haverá problemas para enviá-las novamente para o remoto. Alguma sugestão de como devo proceder?

Manolo
fonte
5
Possível duplicata de Como reverter o repositório Git para um commit anterior?
Trevor Boyd Smith

Respostas:

735

Você pode reverter confirmações individuais com:

git revert <commit_hash>

Isso criará um novo commit que reverterá as alterações do commit que você especificou. Observe que ele apenas reverte esse commit específico e não confirma depois disso. Se você deseja reverter uma série de confirmações, pode fazer o seguinte:

git revert <oldest_commit_hash>..<latest_commit_hash>

Reverte as confirmações entre e incluindo as confirmações especificadas.

Veja a página de manual do git-revert para obter mais informações sobre o git revertcomando. Veja também esta resposta para obter mais informações sobre como reverter confirmações.

gitaarik
fonte
22
Em outras palavras, ele reverte para o <oldest_commit_hash>;)
David
7
@mr_jigsaw Usegit log
gitaarik
2
Na documentação do git, ele diz que o comando revert reverte as confirmações entre a primeira e a última confirmação (tanto a primeira quanto a última são incluídas). Veja a documentação
Onur Demir
4
@ aod está correto, esta resposta precisa ser atualizada. a corrente API git para revert tem <oldest_commit_hash>de ser incluído na lista de reverte
JHixson
4
com o git 2.17.2 revert <old> .. <novo> não inclui antigo, mas inclui <novo>
chingis
353

Uma solução que não mantém vestígios do "desfazer".

NOTA: não faça isso se alguém já tiver efetuado sua alteração (eu usaria isso apenas no meu repo pessoal)

Faz:

git reset <previous label or sha1>

isso fará o check-out de todas as atualizações localmente (para que o status do git listará todos os arquivos atualizados)

você "faz seu trabalho" e reenvia suas alterações (Nota: esta etapa é opcional)

git commit -am "blabla"

Neste momento, sua árvore local difere do controle remoto

git push -f <remote-name> <branch-name>

empurrará e forçará o controle remoto a considerar esse empurrão e removerá o anterior (a especificação de nome remoto e nome da filial não é obrigatória, mas é recomendável evitar a atualização de todas as ramificações com sinalizador de atualização).

!! cuidado, algumas tags ainda podem estar apontando remoção removida! como excluir uma tag remota

jo_
fonte
4
-a todos os arquivos rastreados serão confirmados -m commit message
following
3
Exatamente o que eu procurei. Alguém cometeu um erro, pressionou e reverteu novamente depois. Os ramos não poderia ser fundidos por causa disso e eu queria ter o repositório para estar no estado correto novamente (e remover o commit da história como eram aqueles com defeito de qualquer maneira)
byemute
1
Qual "rótulo anterior ou sha1" devo usar? Devo inserir o último "correto" ou o anterior e refazer todas as alterações feitas pelo último correto?
28416 elysch
3
o primeiro antes do commit
errôneo #
1
Exatamente o que eu preciso. Empurrei um ramo para dominar por engano. E, como resultado, tive muitos commits de lixo durante todo o histórico de commits. Acabei de fazer git push -fa última confirmação correta e o histórico remoto limpo! Obrigado!
Anton Rybalko
193

O que faço nesses casos é:

  • No servidor, mova o cursor de volta para a última confirmação válida:

    git push -f origin <last_known_good_commit>:<branch_name>
    
  • Localmente, faça o mesmo:

    git reset --hard <last_known_good_commit>
    #         ^^^^^^
    #         optional
    



Veja um exemplo completo em uma ramificação my_new_branchque eu criei para esse fim:

$ git branch
my_new_branch

Este é o histórico recente após adicionar algumas coisas a myfile.py:

$ git log
commit 80143bcaaca77963a47c211a9cbe664d5448d546
Author: me
Date:   Wed Mar 23 12:48:03 2016 +0100

    Adding new stuff in myfile.py

commit b4zad078237fa48746a4feb6517fa409f6bf238e
Author: me
Date:   Tue Mar 18 12:46:59 2016 +0100

    Initial commit

Eu quero me livrar do último commit, que já foi enviado, então eu corro:

$ git push -f origin b4zad078237fa48746a4feb6517fa409f6bf238e:my_new_branch
Total 0 (delta 0), reused 0 (delta 0)
To [email protected]:me/myrepo.git
 + 80143bc...b4zad07 b4zad078237fa48746a4feb6517fa409f6bf238e -> my_new_branch (forced update)

Agradável! Agora vejo que o arquivo que foi alterado nesse commit ( myfile.py) é exibido em "não preparado para commit":

$ git status
On branch my_new_branch
Your branch is up-to-date with 'origin/my_new_branch'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   myfile.py

no changes added to commit (use "git add" and/or "git commit -a")

Como não quero essas alterações, apenas movo o cursor de volta localmente também:

$ git reset --hard b4zad078237fa48746a4feb6517fa409f6bf238e
HEAD is now at b4zad07 Initial commit

Então agora o HEAD está no commit anterior, tanto local quanto remoto:

$ git log
commit b4zad078237fa48746a4feb6517fa409f6bf238e
Author: me
Date:   Tue Mar 18 12:46:59 2016 +0100

    Initial commit
fedorqui 'Então pare de prejudicar'
fonte
10
Essa é a resposta correta! este é exatamente o que precisava do ser feito no meu caso, graças aprendeu algo novo hoje :)
Egli Becerra
2
Essa é a resposta correta! É sobre push (!) Confirma!
powtac
3
Se você deseja realmente reverter as alterações (como se nunca as tivesse pressionado), esta é a resposta correta.
1313 Jacob
1
Resposta perfeita. Funcionou bem como esperado!
RafiAlhamd 15/02
2
Alguém compre uma cerveja para este homem!
Jay Nebhwani
72

Você pode REVERT (ou também pode chamá-lo DELETE ) o Git Commit AMB local e remotamente se você seguir as etapas conforme indicado abaixo através da linha de comando git.

Execute o seguinte comando para ver o ID de confirmação que você deseja reverter

git log --oneline --decorate --graph

Você verá uma captura de tela a seguir insira a descrição da imagem aqui

Se você também verificar remotamente (via Interface da Web) , poderá ver que isso seria o mesmo mostrado abaixo

insira a descrição da imagem aqui

Conforme a captura de tela atualmente, você está no ID de confirmação e110322, no entanto, deseja reverter para 030bbf6 AMBOS LOCALMENTE E REMOTAMENTE .

Execute as etapas a seguir para DELETE / REVERT Commits localmente + remotamente


Primeira reversão local para confirmar o ID 030bbf6

git reset --hard 030bbf6

Seguido por

git clean -f -d

Esses dois comandos limpam a força de redefinição para confirmar o estágio 030bbf6, como mostrado abaixo na captura instantânea

insira a descrição da imagem aqui

agora, se você executar o status git, verá que está DOIS comprometidos atrás da ramificação remota, como mostrado abaixo insira a descrição da imagem aqui

Execute o seguinte para atualizar seus índices (se houver alguma atualização). É recomendável que você peça a todos os desenvolvedores para não aceitar solicitações de recebimento na filial remota principal.

git fetch --all

Depois que você terminar, será necessário enviar este commit com força usando o símbolo + na frente do branch, como mostrado abaixo. Eu usei aqui como filial principal , você pode substituí-lo por qualquer

insira a descrição da imagem aqui Código

git push -u origin +master

Agora, se você vir a interface da Web de remote, confirme também deve ser revertida.

insira a descrição da imagem aqui

vibs2006
fonte
61

Isso removerá seus commit enviados

git reset --hard 'xxxxx'

git clean -f -d

git push -f
Mo D Genesis
fonte
7
Este método reescreve corretamente o histórico para excluir a confirmação. Incrível
Jesse Reza Khorasanee
2
esta resposta é el magnifeco!
truthadjustr
3
Ame a resposta, obrigado :)
Dzenis H. 25/01
1
Só para esclarecer (não tinha certeza): o commit será o commit atual após a operação. Não é o último a excluir.
Maik639 30/04
21
git revert HEAD -m 1

Na linha de código acima. "Último argumento representa"

  • 1 - reverte uma confirmação.

  • 2 - reverte os últimos dois commits.

  • n - reverte o último n confirma.

Você precisa pressionar este comando para ativar o controle remoto. Você tem outras opções, como especificar o intervalo de confirmações para reverter. Essa é uma das opções.


Mais tarde, use git commit -am "COMMIT_MESSAGE" então git pushougit push -f

Sireesh Yarlagadda
fonte
8
Isso não é verdade - o parâmetro -m especifica o número de pais para os quais reverter (normalmente 1 se você deseja reverter as alterações recebidas, "deles", em oposição a 2 para alterações mescladas, "nosso" - para mesclar 2 confirma). Não tem nada a ver com o número de confirmações revertidas - se você quiser reverter um intervalo de confirmação, usegit revert ref1..ref2
Referência nula
1
Não teve o efeito desejado
Sam Tuke
4

2020 maneira simples:

git reset <commit_hash>

(O hash do último commit que você deseja manter).

Você manterá as alterações agora não confirmadas localmente.

Se você deseja pressionar novamente, você deve fazer:

git push -f
Xys
fonte
0

Aqui está o meu caminho:

Digamos que o nome do ramo seja develop.

# Create a new temp branch based on one history commit
git checkout <last_known_good_commit_hash>
git checkout -b develop-temp

# Delete the original develop branch and 
# create a new branch with the same name based on the develop-temp branch
git branch -D develop
git checkout -b develop

# Force update this new branch
git push -f origin develop

# Remove the temp branch
git branch -D develop-temp
backslash112
fonte
0

Você pode fazer algo como

git push origin +<short_commit_sha>^:<branch_name>
avrsanjay
fonte