Desfazer uma mesclagem por solicitação pull?

159

Alguém aceitou uma solicitação pull que não deveria ter. Agora temos um monte de códigos quebrados incorporados. Como você desfaz uma solicitação pull? Ia reverter as alterações no commit antes da mesclagem, mas notei que ele se mesclava em vários commits. Portanto, agora existem todos esses commits dessa pessoa dias antes da mesclagem. Como você desfaz isso?

Vai
fonte
7
Apesar do conselho da resposta aceita, POR FAVOR, não force o envio a um repositório se o repositório for compartilhado com mais ninguém. Você corre o risco de arruinar o trabalho que outros fizeram e o GitHub pode continuar mostrando a solicitação de recebimento como tendo sido mesclada. Outra resposta a esta pergunta explica uma maneira mais segura de desfazer uma solicitação de recebimento.
alxndr
2
Nota: pelo menos agora (junho de 2014), o GitHub propõe o botão "Reverter" em sua GUI da web de solicitação de recebimento. Veja minha resposta abaixo
VonC
1
O problema com o botão de reversão é que ele cria uma nova confirmação como inversa à solicitação de recebimento, o que significa que se você deseja mesclar essas alterações, o uso do botão "Revert" pode tornar isso muito mais difícil.
FluffySamurai

Respostas:

159

Existe uma resposta melhor para esse problema, embora eu pudesse apenas detalhar isso passo a passo.

Você precisará buscar e efetuar o checkout das alterações upstream mais recentes, como por exemplo:

git fetch upstream
git checkout upstream/master -b revert/john/foo_and_bar

Examinando o log de confirmação, você deve encontrar algo semelhante a este:

commit b76a5f1f5d3b323679e466a1a1d5f93c8828b269
Merge: 9271e6e a507888
Author: Tim Tom <[email protected]>
Date:   Mon Apr 29 06:12:38 2013 -0700

    Merge pull request #123 from john/foo_and_bar

    Add foo and bar

commit a507888e9fcc9e08b658c0b25414d1aeb1eef45e
Author: John Doe <[email protected]>
Date:   Mon Apr 29 12:13:29 2013 +0000

    Add bar

commit 470ee0f407198057d5cb1d6427bb8371eab6157e
Author: John Doe <[email protected]>
Date:   Mon Apr 29 10:29:10 2013 +0000

    Add foo

Agora você deseja reverter toda a solicitação de recebimento com a capacidade de reverter mais tarde. Para fazer isso, você precisará levar o ID da confirmação de mesclagem .

No exemplo acima, a consolidação de mesclagem é a principal, onde diz "Solicitação de recebimento mesclado nº 123 ..." .

Faça isso para reverter as duas alterações ( "Adicionar barra" e "Adicionar foo" ) e você terminará com um commit revertendo toda a solicitação pull, que poderá ser revertida posteriormente e manter limpo o histórico de alterações:

git revert -m 1 b76a5f1f5d3b323679e466a1a1d5f93c8828b269
errordeveloper
fonte
6
Essa deve ser a resposta correta. Há uma referência na página man git-revert para obter mais detalhes da lista de discussão git aqui kernel.org/pub/software/scm/git/docs/howto/...
Justin Hamade
2
Por que o git checkout upstream/master -b revert/john/foo_and_bar? o que isso faz exatamente?
Magne
4
@Magne - você está criando uma nova ramificação para fazer a reversão, na qual pode escolher onde mesclar a reversão. Basicamente, apenas lhe dá mais controle sobre o que fazer com o ramo. No meu caso, enviei uma nova solicitação pull desta ramificação "fixa" contendo a reversão de volta para nossa ramificação de desenvolvimento, o que significa que minha nova solicitação pull também pode ser revertida, se necessário. Isso foi feito para uma versão em que decidimos retirar o primeiro rascunho de um recurso que foi reagendado. Nenhum código incorreto, apenas não indo nesta versão.
Daniel Nalbach 30/10
3
Eu aprendi uma lição difícil sobre este. Introduzimos um recurso em nossa filial de desenvolvimento, mas percebemos que havia problemas de dados e revertemos diretamente no desenvolvimento. Mais tarde, quando as coisas foram corrigidas, queríamos adicionar recursos de desenvolvimento mais recentes a esse ramo para testar sua compatibilidade com esse recurso antes de enviar por push, então eu mesclou o desenvolvimento de volta ao ramo de recursos. Isso também aplicou a confirmação de reversão, que cancelou todas as alterações feitas na ramificação do recurso. > <
Greg
86

Veja o seu gráfico de confirmação (com gitk ou um programa similar). Você verá confirmações da solicitação pull e verá suas próprias confirmações e uma confirmação de mesclagem (se não for uma mesclagem de avanço rápido). Você apenas precisa encontrar o último de seus commit antes da mesclagem e redefinir a ramificação para esse commit.

(Se você tiver o reflog do ramo, deve ser ainda mais fácil encontrar o commit antes da mesclagem.)


(Edite depois de mais informações nos comentários :)

Ok, vamos olhar para o gráfico:

captura de tela 1

Presumo que o último commit (mais à direita) foi sua solicitação de mesclagem errada por pull , que mesclou a linha azul vista aqui. Sua última boa cometer seria o anterior na linha de preto, aqui marcados em vermelho:

insira a descrição da imagem aqui

Redefina para este commit e você deve ficar bem.

Isso significa que, na sua cópia de trabalho local, faça isso (depois de verificar se você não possui mais itens não confirmados, por exemplo, pelo git stash):

git checkout master
git reset --hard 7a62674ba3df0853c63539175197a16122a739ef
gitk 

Agora confirme que você está realmente no commit que eu marquei lá, e você não verá nenhuma das coisas puxadas em sua ancestralidade.

git push -f origin master

(se o seu github remote for nomeado origin- altere o nome).

Agora, tudo deve estar correto também no github. As confirmações ainda estarão no seu repositório, mas não poderão ser acessadas por nenhum ramo, portanto, não devem causar nenhum dano a ele. (E eles ainda estarão no repositório de RogerPaladin, é claro.)

(Pode haver uma maneira apenas específica da Web do Github de fazer a mesma coisa, mas não estou muito familiarizado com o Github e seu sistema de gerenciamento de solicitações de recebimento.)

Observe que se alguém já tiver puxado seu mestre com a confirmação incorreta, eles terão o mesmo problema que você atualmente e não poderão realmente contribuir de volta. antes de redefinir para sua nova versão principal.

Se é provável que isso aconteceu, ou você simplesmente deseja evitar problemas, use o git revertcomando em vez de git reset, para reverter as alterações com uma nova confirmação, em vez de voltar para uma anterior. (Algumas pessoas pensam que você nunca deve redefinir com ramificações publicadas.) Veja outras respostas para esta pergunta sobre como fazer isso.

Para o futuro:

Se você deseja apenas alguns dos commit da filial de RogerPaladin, considere usar em cherry-pickvez de merge. Ou comunique-se com RogerPaladin para movê-los para uma ramificação separada e enviar uma nova solicitação de recebimento.

Paŭlo Ebermann
fonte
Mas temos uma tonelada de confirmações entre a mesclagem e seu primeiro commit. Então, como nós temos o commit de mesclagem, o nosso próprio confirma e depois outro commit por ele. Parece que ele se fundiu em compromissos muito antigos dele.
Will
Sim, ele será mesclado em tudo que é um ancestral do commit mesclado (e ainda não é um ancestral do commit). Isso não deve impedi-lo de redefinir - os commits não serão reordenados por eles mesmos, se você não fez uma nova rebase posteriormente.
Paŭlo Ebermann 26/06
1
Sim, agora parece correto (além da estranha fusão entre si - mas isso pode ser uma falha no software de gráfico de rede). :-) Estou feliz por poder ajudar.
Paŭlo Ebermann 26/06
6
Acho que isso pode ser problemático se alguém tiver retirado os commits ruins e, posteriormente, enviar uma solicitação de pull que contenha os mesmos commits ruins; Não seria mais seguro criar um novo commit que reverta os commits ruins? Dessa forma, se os maus commits tiverem sido puxados para outros galhos / garfos, eles serão efetivamente removidos por outro puxão para aquele outro galho / garfo? Não estou afirmando isso como fato, é o que penso ser verdade, estando na mesma posição do OP e tendo passado uma hora ou mais considerando minhas opções.
Myles McDonnell
4
@ Eu sugeriria não aceitar esta resposta. Isso é bom para código que ainda não foi enviado por push (nesse caso, essa é uma pergunta SO mais relevante, mas para código compartilhado publicamente, executando um comando git que reescreve o histórico (nesse caso, reset --harde um push forçado é muito má prática) a resposta por @errordeveloper abaixo mostra uma maneira de fazer isso sem qualquer história reescrita ou força empurrando..
asmeurer
34

Se a atração foi a última coisa que ele fez, então

git reset --hard HEAD~1
samthebest
fonte
3
tenha cuidado ao seguir esta instrução, ela realmente me atrasou 2 etapas, não uma.
precisa saber é
1
@szeitlin Como aconteceu que você levou dois passos para trás, não um? Sei que este comentário foi deixado há mais de 4 anos, mas estou curioso para saber se alguém sabe como responder. Isso é muito importante para mim. Obrigado.
21316 Haradzieniec
Não me lembro agora, mas acho que isso poderia acontecer se eu tivesse feito um novo commit quando tentei redefinir? Gostaria de testá-lo com um repo fictício se você estiver preocupado com isso.
Szeitlin 6/06/16
Este funcionou bem para mim. Excluiu a solicitação de recebimento mesclada recentemente. Depois git reset --hard HEAD~1, eu costumava git push origin -fatualizar o repositório remoto. Mas tenha cuidado, tenha cuidado antes de fazer isso.
Denis Oluka 10/01
24

A partir de 24 de junho de 2014, você pode tentar cancelar um PR facilmente (consulte " Revertendo uma solicitação de recebimento ") com:

Apresentando o botão Reverter

você pode reverter facilmente uma solicitação de recebimento no GitHub clicando em Revert:

https://camo.githubusercontent.com/0d3350caf2bb1cba53123ffeafc00ca702b1b164/68747470733a2f2f6769746875622d696d616765732e73332e616d617a6f6e6177732e636f6d2f68656c702f70756c6c5f72657175657374732f7265766572742d70756c6c2d726571756573742d6c696e6b2e706e67

Você será solicitado a criar uma nova solicitação de recebimento com as alterações revertidas:

https://camo.githubusercontent.com/973efae3cc2764fc1353885a6a45b9a518d9b78b/68747470733a2f2f6769746875622d696d616765732e73332e616d617a6f6e6177732e636f6d2f68656c702f70756c6c5f72657175657374732f7265766572742d70756c6c2d726571756573742d6e65772d70722e706e67

Resta ainda ser testado se essa reversão usa -mou não (para reverter mesclagens também)

Mas Adil H Raza acrescenta nos comentários (dezembro de 2019):

Esse é o comportamento esperado, ele criou uma nova ramificação e você pode criar um PR dessa nova ramificação para a sua master.
Dessa forma, no futuro, você pode cancelar a reversão da reversão, se necessário, é a opção mais segura e não altera diretamente a sua master.


Atenção : Korayem ressalta nos comentários que:

Após uma reversão, digamos que você fez algumas alterações adicionais na ramificação do Git e criou um novo PR a partir da mesma ramificação de origem / destino.
Você encontrará o PR mostrando apenas novas alterações, mas nada do que estava lá antes de reverter .

Korayem nos refere ao " Github: Alterações ignoradas após reverter ( git cherry-pick, git rebase) " para mais.

VonC
fonte
Eu tentei isso e ele criou um novo ramo em vez de desfazer PR no mestre?
precisa
Estranho. Você poderia fazer uma nova pergunta para ilustrar esse comportamento?
VonC 15/03/19
esse é o comportamento esperado, ele criou uma nova ramificação e você pode criar um PR dessa nova ramificação para o seu mestre. Dessa forma, no futuro, você pode cancelar a reversão da reversão, se necessário, é a opção mais segura e não altera diretamente o seu mestre.
Adil H. Raza
1
@ AdilH.Raza Obrigado. Incluímos seu comentário na resposta para obter mais visibilidade.
VonC 05/12/19
1
Os dedos do @VonC cruzaram isso para evitar que os desenvolvedores de todo o mundo
sofram
8

Para desfazer uma solicitação pull do github com confirmações que você não deseja excluir, é necessário executar um:

git reset --hard --merge <commit hash>

com o hash de confirmação sendo o commit ANTES de mesclar a solicitação de recebimento. Isso removerá todas as confirmações da solicitação de recebimento sem influenciar nenhuma confirmação no histórico.

Uma boa maneira de encontrar isso é ir para a solicitação pull agora fechada e localizar este campo:

Pull Request Image Pull Request Image

Depois de executar o git reset, execute um:

git push origin --force <branch name>

Isso deve reverter a ramificação antes da solicitação pull, sem afetar nenhuma confirmação na ramificação inserida no histórico de confirmação entre confirmações da solicitação pull.

EDITAR:

Se você clicar no botão reverter na solicitação de recebimento, isso criará uma confirmação adicional na ramificação. NÃO descompacta ou descompacta. Isso significa que, se você apertar o botão de reversão, não poderá abrir uma nova solicitação pull para adicionar novamente todo esse código.

FluffySamurai
fonte
Ótima maneira de fazer as coisas endireitaram sem necessidade de qualquer Revertendo louco ou cherry-picking
Cumulo Nimbus
Obrigado! Era isso que eu estava planejando fazer, mas isso teria sido em torno de 200 comprometidos com a escolha.
FluffySamurai
1

Eu uso esse lugar o tempo todo, obrigado.

Eu estava procurando como desfazer uma solicitação pull e cheguei aqui.

Eu estava prestes a git reset --hard"muito tempo atrás" e avançar rapidamente de volta para onde estava antes de fazer a solicitação de recebimento.

Além de procurar aqui, também perguntei ao meu colega de trabalho o que ele faria e ele tinha uma resposta normalmente boa: usando o exemplo de saída na primeira resposta acima:

git reset --hard 9271e6e

Como na maioria das coisas no Git, se você está fazendo algo de alguma maneira que não é fácil, provavelmente está fazendo errado.

Mike Marshall
fonte