Redefinindo o controle remoto para um determinado commit

709

Quero descartar todas as alterações feitas após a confirmação <commit-hash>. Então eu fiz:

git reset --hard <commit-hash>

Agora eu quero fazer o mesmo com o meu controle remoto. Como posso fazer isso? Fiz alguns commit (e empurra) depois <commit-hash>e só quero descartar todos. É apenas algo que deu muito errado no caminho e eu não quero piorar as coisas do que já são. ; (

Basicamente, eu quero rebobinar minha origin/masterpara<commit-hash>

nacho4d
fonte
3
Tem certeza de origin/masterque não foi puxado e pressionado por outros usuários? Alterar o histórico de um repositório público (ou seja, não local) é algo que você deseja evitar o tempo todo.
Vindia
Possível duplicata de Como reverter vários commits git?
Michael Freidgeim 02/09

Respostas:

1252

Supondo que sua ramificação seja chamada masteraqui e remotamente, e que seu controle remoto seja chamado, originvocê pode:

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

No entanto, você deve evitar fazer isso se mais alguém estiver trabalhando com seu repositório remoto e tiver feito suas alterações. Nesse caso, seria melhor reverter as confirmações que você não deseja e depois pressionar normalmente.

Atualização: você explicou abaixo que outras pessoas realizaram as alterações que você enviou, por isso é melhor criar um novo commit que reverta todas essas alterações . Há uma boa explicação de suas opções para fazer isso nesta resposta de Jakub Narębski . Qual é o mais conveniente depende de quantos commits você deseja reverter e qual método faz mais sentido para você.

Como a partir de sua pergunta, é claro que você já usou git reset --hardpara redefinir sua masterramificação, pode ser necessário começar usando-a git reset --hard ORIG_HEADpara mover sua ramificação de volta para onde estava antes. (Como sempre git reset --hard, verifique se git statusestá limpo, se você está no ramo certo e se conhece git reflogcomo uma ferramenta para recuperar confirmações aparentemente perdidas.) Você também deve verificar se ORIG_HEADaponta para a confirmação correta git show ORIG_HEAD.

Solução de problemas:

Se você receber uma mensagem como " ! [Rejeitado remotamente] a60f7d85 -> master (gancho de pré-recebimento recusado) "

é necessário permitir a reescrita do histórico da ramificação para a ramificação específica. No BitBucket, por exemplo, dizia "Não é permitido reescrever o histórico de ramificações". Há uma caixa de seleção com o nome Allow rewriting branch historyque você deve verificar.

Mark Longair
fonte
21
Perigo Perigo: essa redefinição pressupõe que o ramo correspondente ( rastreamento ) esteja com check-out no momento e que não haja alterações não confirmadas que você deseja manter. Use em git update-refvez dereset --hard ; ele permitirá que você a fazer o mesmo sem ter uma árvore de trabalho / check-out branch
sehe
3
Eu vejo. Foi empurrado e alterado por outros. Então, eu devo usar, revert mas digamos que eu queira reverter os últimos 4 commits, então devo fazer git revert comit1; git push; git revert comit2; git push; ...ou simplesmente git revert commit4; git push?
N
1
@ nacho4d: você não precisa pressionar após cada reversão - há uma boa descrição do que fazer nesta resposta de Jakub Narębski . Você precisa reverter cada confirmação para trás - basta git revert commit4criar uma nova confirmação que apenas desfaz as alterações introduzidas commit4. Como a resposta a que vinculei, porém, você pode transformá-las em um único commit.
precisa saber é o seguinte
1
@ Mark Já executei, git reset --hardmas excluí meu local e retirei da origem novamente, para poder fazer git revert ...agora. Minha dúvida agora é: tenho que reverter cada commit e push (um por um) ou apenas reverter o primeiro commit após o certo comprometer apenas?
N /
1
@sehe: é difícil de usar, porque você precisa usar o nome completo da referência e, portanto, é fácil para as pessoas ocupar seu .gitdiretório com referências que elas não pretendiam criar. Eu errei ao dizer que não há verificações de segurança. Você pode encontrar a classificação nos comandos "encanamento" e "porcelana" na página de manual do git .
precisa saber é o seguinte
123

Use as outras respostas se não se importar em perder alterações locais. Esse método ainda pode destruir seu controle remoto se você escolher o hash de confirmação errado para o qual voltar.

Se você quiser apenas fazer com que o controle remoto corresponda a um commit que esteja em qualquer lugar do seu repositório local:

  1. Você não fazer nenhum reajuste.
  2. Use git logpara encontrar a confirmação na qual você deseja que o controle remoto esteja. git log -ppara ver mudanças ou git log --graph --all --oneline --decoratepara ver uma árvore compacta.
  3. Copie o hash ou a marca do commit ou o nome de sua ramificação, se for a dica.
  4. Execute um comando como:

    git push --force <remote> <commit-ish>:<the remote branch>
    

    por exemplo

    git push --force origin 606fdfaa33af1844c86f4267a136d4666e576cdc:master
    

    ou

    git push --force staging v2.4.0b2:releases
    

Eu uso o alias conveniente ( git go) para visualizar o histórico como na etapa 2, que pode ser adicionada da seguinte forma:

    git config --global alias.go 'log --graph --all --decorate --oneline'`
Walf
fonte
3
O gráfico foi uma dica muito legal, eu adicionei -5 para obter apenas o último n commit, era uma árvore enorme. Também evitar a redefinição é exatamente o que eu estava procurando. Grande
Alexanderd
@AlexanderD Você também pode adicionar o alias ao Git, e não ao seu shell, para que funcione em qualquer lugar. O Git entende esses aliases e tabulações completas no comando completo para que você possa adicionar argumentos. git config --global alias.graph 'log --graph --all --decorate --oneline'é menos confuso e você ainda pode limitá-lo, por exemplo:git graph -5
Walf 13/12
Isto é perfeito. Eu sempre estraguei meu local. Este foi exatamente o que eu precisava após acidentalmente empurrando meu preparo para viver :( Thanks!
Jake
1
No Windows, digite qpara sair do log do git. 2 minutos eu nunca voltarei.
dst3p
1
@ dst3p Está em todas as plataformas, companheiro. O programa de pager é geralmente lesse qé a maneira normal de sair dele. O Git Bash é como um terminal * nix.
Walf
63

Resolvi um problema como o seu com estes comandos:

git reset --hard <commit-hash> 
git push -f <remote> <local branch>:<remote branch> 
Ibrohim Ermatov
fonte
13

No GitLab, talvez você precise configurar sua ramificação para desprotegida antes de fazer isso. Você pode fazer isso em [repositório]> Configurações> Repositório> Ramos protegidos. Então o método da resposta de Mark funciona.

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

Se você deseja uma versão anterior do arquivo, eu recomendaria o uso do git checkout.

git checkout <commit-hash>

Isso enviará você de volta no tempo, não afeta o estado atual do seu projeto, você pode acessar a linha principal do git checkout mainline

mas quando você adiciona um arquivo no argumento, esse arquivo é trazido de volta de uma hora anterior para a hora atual do seu projeto, ou seja, seu projeto atual é alterado e precisa ser confirmado.

git checkout <commit-hash> -- file_name
git add .
git commit -m 'file brought from previous time'
git push

A vantagem disso é que ele não exclui o histórico e nem reverte uma alteração específica de código (git revert)

Confira mais aqui https://www.atlassian.com/git/tutorials/undoing-changes#git-checkout

priya khokher
fonte
Esta é uma excelente resposta: funciona, ponto e é muito seguro; se você estragar tudo, é fácil voltar.
bob
8

Meus dois centavos para as respostas anteriores: se

git push --force <remote> <the-hash>:<the remote branch>

ainda não funciona, convém editar <your-remote-repo>.git/configa seção de recebimento do arquivo:

[receive]
  #denyNonFastforwards = true
  denyNonFastforwards = false
badbishop
fonte
É útil saber como configurar um controle remoto para permitir impulsos de avanço rápido, pois a maioria das respostas parece assumir um serviço remoto como o github ou o bitbucket.
strongbutgood
2

Se o seu ramo não for desenvolvimento ou produção, a maneira mais fácil de conseguir isso é redefinir para um determinado commit localmente e criar um novo ramo a partir daí. Você pode usar:

git checkout 000000

(onde 000000 é o ID de confirmação para onde você deseja ir) em sua ramificação problemática e, em seguida, simplesmente crie uma nova ramificação:

git remote add [nome_do_seu_remote]

Então você pode criar um novo PR e tudo funcionará bem!

Gerardo Suarez
fonte
1

Faça uma coisa, obtenha o SHA do commit não. como 87c9808 e, em seguida,

  1. mova-se, essa é a sua cabeça para o commit especificado (fazendo git reset --hard 89cef43 // mencione seu número aqui)
  2. Em seguida, faça algumas alterações em um arquivo aleatório, para que o git peça para você confirmar isso localmente e depois remotamente. Assim, o que você precisa fazer agora é. depois de aplicar a mudança git commit -a -m "trial commit"
  3. Agora, envie o seguinte commit (se este tiver sido confirmado localmente) pelo git push origin master
  4. Agora, o que o git vai pedir de você é que

error: falha ao enviar algumas referências à dica ' https://github.com/YOURREPOSITORY/AndroidExperiments.git ': as atualizações foram rejeitadas porque a dica de sua ramificação atual está por trás da dica: sua contraparte remota. Integre as alterações remotas (por exemplo, dica: 'git pull ...') antes de pressionar novamente. **

  1. Então agora o que você pode fazer é

git push --force origin master

  1. E assim, espero que funcione :)
Siddharth Choudhary
fonte
1

Sourcetree: redefinindo o controle remoto para um determinado commit

  1. Se você enviou um commit incorreto ao seu controle remoto (origin / feature / 1337_MyAwesomeFeature) como na figura abaixo

Ir para controles remotos

  1. Vá para Remotos> origem> recurso> 1337_MyAwesomeFeature
  2. Clique com o botão direito do mouse e escolha "Excluir origem / recurso / 1337_MyAwesomeFeature" (ou altere o nome dele se desejar um backup e pule a etapa 4.)
  3. Clique em "Forçar exclusão" e "OK".

insira a descrição da imagem aqui insira a descrição da imagem aqui

  1. Selecione sua confirmação mais antiga e escolha "Redefinir ramificação atual para esta confirmação"
  2. Escolha o modo que você deseja ter (Difícil, se você não quiser as últimas alterações) e "OK".

insira a descrição da imagem aqui insira a descrição da imagem aqui

  1. Envie esta confirmação para uma nova origem / recurso / 1337_MyAwesomeFeature insira a descrição da imagem aqui

  2. Seu ramo de recursos local e seu ramo de recursos remotos agora estão no commit anterior (de sua escolha) insira a descrição da imagem aqui

Joel Wiklund
fonte