Revertendo o repositório git local e remoto por 1 confirmação


188

Eu li os posts semelhantes sobre este tópico e, durante toda a minha vida, não consigo descobrir como fazer isso corretamente.

Fiz o check-in de cerca de 1000 arquivos que não quero e prefiro não precisar passar por 1by1 e removê-los do repositório.

  • Eu tenho um masterramo remoto .
  • Eu tenho a masterfilial local .

Ambos estão na mesma revisão.

Eu quero reverter meu controle remoto por 1 commit.

Diga que minha história masteré A--B--C--D--E.
Eu quero reverter meu local para D.
Em seguida, empurre-o para controle remoto para que meu hash atual seja D remoto e local.

Estou tendo problemas para fazer isso.
Estou usando o Git Tower, mas estou confortável com a linha de comando. Qualquer ajuda?

ATUALIZAÇÃO: Ótimos comentários abaixo. O uso de uma redefinição parece desanimado, principalmente se o repositório for compartilhado com outros usuários. Qual é a melhor maneira de desfazer as alterações do commit anterior sem usar uma redefinição física ? Há algum jeito?


Atualizei minha resposta para "desfazer as alterações do commit anterior sem usar uma reinicialização completa".
— VonC

3
Use git revertpara fazer sem redefinições rígidas e sem incomodar os usuários.
— precisa saber é o seguinte


Reverter o controle remoto é o que é desencorajado, mas se é isso que você deseja fazer, faça-o. Existem centenas de maneiras de fazer isso, mas o resultado seria o mesmo no lado do servidor.
— FelipeC 07/06/19

Respostas:


307

Se ninguém conseguiu o seu repo remoto ainda, você pode alterar o HEAD do seu ramo e forçar o envio para o repo remoto:

git reset --hard HEAD^ 
git push -f 

(ou, se você tiver acesso direto ao repositório remoto, poderá alterar a referência HEAD, mesmo que seja um repositório simples )

Observe que, conforme comentado pela tecnologia alienígena nos comentários abaixo , no Windows (sessão CMD), você precisaria de ^^:

git reset --hard HEAD^^
git push -f 

Atualização desde 2011: o
uso git push --force-with-lease( que apresento aqui , introduzido em 2013 com o Git 1.8.5) é mais seguro.

Veja a resposta de Schwern para ilustração.


E se alguém já puxou o repositório? O que eu faria então?

Então eu sugiro algo que não reescreva a história:

  • git revert localmente seu último commit (criando um novo commit que reverte o que o commit anterior fez)
  • empurre o 'reverter' gerado por git revert.

1
E se alguém já puxou o repositório? O que eu faria então?
— Jamis Charles

1
@gwho cria uma filial? Não, ele move o HEAD de um ramo, mas você ainda está no mesmo ramo. No entanto, como o push não é mais um avanço rápido, sim, você precisa forçá-lo.
— VonC 01/07/19

1
existe uma maneira de saber se alguém retirou o repositório?
— Pinkerton

4
No Windows, o personagem ^ é usado para linha de continuação e para escapar de um personagem, tornando o comando: git reset CABEÇA --hard ^^
— Tecnologia estrangeira

1
@AlienTechnology Usando o Powershell, no Windows 10, eu só precisava digitar reset --hard HEAD^e não reset --hard HEAD^^redefinir a última confirmação.
— Gaspacchio 30/01/19

58

Defina a filial local uma revisão novamente ( HEAD^significa uma revisão novamente):

git reset --hard HEAD^

Envie as alterações para a origem:

git push --force

Você terá que forçar o empurrão porque, caso contrário, o git reconheceria que você está atrasado originpor um commit e nada vai mudar.

Fazer isso com o --forcegit para sobrescrever HEADno repositório remoto sem respeitar os avanços lá.


1
Eu sugeriria não chamar isso de reversão, pois esse é um termo específico com um significado muito diferente no git.
— Cascabel

@ Jeffromi: Obrigado pela dica. Editado.
— Eckes

Ótima resposta. Eu li que o uso de uma redefinição parece parcialmente desencorajado, especialmente se o repositório for compartilhado com outros usuários. Existe uma maneira mais limpa de fazer isso, que desfaz todas as alterações do commit anterior?
— Jamis Charles

Seja cuidadoso! Esconder suas alterações não confirmadas ou seu perdido los
— Nosov Pavel

Isso é legal. Então, isso significa que, quando o fazemos git push origin master, o Git é capaz de criar um novo commit no controle remoto porque o ramo local está à frente pelo menos uma vez no commit? Além disso, o último deve ser substancialmente diferente do que a cabeça do repositório remoto aponta?
— MadPhysicist

18

Se você deseja reverter a última confirmação, ouça:

Passo 1:

Verifique as confirmações locais com mensagens

$ git log

Passo 2:

Remova a última confirmação sem redefinir as alterações da ramificação local (ou principal)

$ git reset HEAD^

OU se você não deseja que os últimos arquivos e atualizações de confirmação ouçam

$ git reset HEAD^ --hard

Etapa 3:

Podemos atualizar os arquivos e códigos e, novamente, precisamos pressionar com força para excluir a confirmação anterior. Manterá um novo commit.

$ git push origin branch -f

É isso aí!


Isso não está revertendo um commit, está substituindo um. Por favor, não nos confunda git novatos, abusando dos termos convencionais.
— Suncat2000

7

Ao digitar o comando abaixo, você pode ver seu histórico de confirmação do git -

$ git log

Digamos que seu histórico nesse ramo específico seja como - commit_A, commit_B, commit_C, commit_D. Onde, commit_D é o último commit e é aí que o HEAD permanece. Agora, para remover seu último commit do local e do remoto, você deve fazer o seguinte:

Etapa 1: remova a última confirmação localmente por -

$ git reset --hard HEAD ~

Isso mudará seu commit HEAD para commit_C

Etapa 2: envie sua alteração para o novo commit HEAD para controle remoto

origem do push $ git + HEAD

Este comando excluirá a última confirmação do controle remoto.

PS: este comando foi testado no Mac OSX e também deve funcionar em outros sistemas operacionais (embora não afirme outro sistema operacional)



3

Aqui está uma versão atualizada do procedimento, que é mais segura.

git reset --hard HEAD^ 
git push --force-with-lease

git push -fsubstituirá indiscriminadamente o repositório remoto por suas próprias alterações. Se alguém empurrou as alterações, elas serão perdidas. git push --force-with-leaseapenas enviará sua rebase se o repositório estiver como o esperado. Se alguém já tiver pressionado o seu push falhará.

Veja - força considerada prejudicial; entender a força do contrato do git .

Eu recomendo aliasing isso como repush = push --force-with-lease.

E se alguém já puxou o repositório? O que eu faria então?

Diga para eles git pull --rebase=merges. Em vez de um git fetch origine git merge origin/masterserá git fetch origine git rebase -r origin/master. Isso reescreverá qualquer uma das alterações locais masterno topo da nova versão reestruturada origin/master. -rpreservará quaisquer fusões que eles possam ter feito.

Eu recomendo fazer deste o comportamento padrão para puxar. É seguro, manipulará o rebase de outras pessoas e resultará em mesclagens menos desnecessárias.

[pull]
        rebase = merges

1
Concordado e votado. Para minha defesa, minha antiga resposta de 2011 foi escrita dois anos antes da introdução da --force-with-leaseopção.
— VonC 30/01

Eu pensei que já fiz isso (ontem): stackoverflow.com/posts/4647362/revisions
— VonC 01/02

1

Resolvi um problema como o seu com estes comandos:

git reset --hard HEAD^
git push -f <remote> <local branch>:<remote branch> 


0

Eu só queria remover o último commit do histórico de commit remoto e claro também. O seguinte funcionou como um encanto

git reset --hard HEAD^ 
git push -f 

Mas como "o seguinte" é diferente da minha resposta acima ?
— VonC 12/08/2015

0

A maneira de redefinir a cabeça e reverter para o commit anterior é através

$ git reset HEAD^ --hard
$ git push <branchname> -f

Mas, às vezes, pode não ser aceito na ramificação remota:

To ssh:<git repo>
 ! [rejected]        develop -> develop (non-fast-forward)
error: failed to push some refs to 'ssh:<git repo>'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

então a outra maneira de fazer é

git revert HEAD
git push <remote branch>

Isso funciona bem.

NOTA: lembre-se de ter git push -f <force>falhado e tente reverter. Faça um git pullantes, para que o local e o remoto estejam sincronizados e tente git revert.
Verifique com git logpara garantir que o remoto e o local estejam no mesmo ponto de confirmação com o mesmo SHA1.

git revert 
A --> B --> C -->D
A--> B --> C --> D --> ^D(taking out the changes and committing reverted diffs)

0

no mestre local

git reflog
-- this will list all last commit
  e.g Head@{0} -- wrong push
      Head@{1} -- correct push  
git checkout Head@{1} .
  -- this will reset your last modified files

git status 
git commit -m "reverted to last best"
git push origin/master

Não precisa se preocupar se outro puxou ou não.

Feito!


0

Se você deseja remover apenas a última confirmação do repositório remoto sem mexer com o repositório local, aqui está uma lista:

git push origin +origin/master~:master

Isso usa a seguinte sintaxe:

git push <remote> <refspec>

Aqui, <remote>é origine <refspec>tem a seguinte estrutura:

+origin/master~:master

Detalhes podem ser encontrados em git-push(1). O anterior +significa "force push this ref", e a outra parte significa "from origin/master~to master(of remote origin)". Não é difícil saber qual origin/master~é o último commit antes origin/master, certo?


0

para mim trabalha estes dois comandos:

git checkout commit_id
git push origin +name_of_branch

0

Você também pode fazer isso:

git reset --hard <commit-hash>
git push -f origin master

e todos os outros que receberam as últimas confirmações ruins foram redefinidos:

git reset --hard origin/master
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.