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?

Jamis Charles
fonte
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
2
Possível duplicado de commits DELETE FROM uma filial na Git
wjandrea
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.
VonC
fonte
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á.

eckes
fonte
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í!

Kannan S
fonte
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)

sahilabrar
fonte
3

Para máquinas Windows, use:

git reset HEAD~1  #Remove Commit Locally
Anvesh Yalamarthy
fonte
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
Schwern
fonte
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> 
Ibrohim Ermatov
fonte
0

Se você tiver acesso direto ao repositório remoto, sempre poderá usar:

git reset --soft HEAD^

Isso funciona, pois não há nenhuma tentativa de modificar o diretório de trabalho inexistente. Para mais detalhes, consulte a resposta original:

Como posso descomprimir o último commit em um repositório git bare?

Hazok
fonte
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 
minhas23
fonte
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)
ravi.zombie
fonte
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!

Bhushan
fonte
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?

iBug
fonte
0

para mim trabalha estes dois comandos:

git checkout commit_id
git push origin +name_of_branch
Yahor M
fonte
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
A-Sharabiani
fonte