Annullare un'unione mediante richiesta pull?


159

Qualcuno ha accettato una richiesta pull che non avrebbe dovuto avere. Ora abbiamo un sacco di codice rotto unito. Come si annulla una richiesta pull? Stavo per annullare le modifiche al commit appena prima della fusione, ma ho notato che si è fuso in un mucchio di commit. Quindi ora ci sono tutti questi commit da questa persona da giorni prima della fusione. Come si annulla questo?


7
Nonostante il consiglio della risposta accettata, PER FAVORE non forzare il push in un repository se il repository è condiviso con qualcun altro. Corri il rischio di rovinare il lavoro svolto da altri e GitHub potrebbe continuare a mostrare che la richiesta pull è stata unita. Un'altra risposta a questa domanda spiega un modo più sicuro per annullare una richiesta pull.
alxndr,

2
Nota: almeno ora (giugno 2014), GitHub propone il pulsante "Ripristina" nella GUI Web della richiesta pull. Vedi la mia risposta di seguito
VonC,

1
Il problema con il pulsante Ripristina è che crea un nuovo commit come inverso alla richiesta pull, il che significa che se si desidera unire alla fine queste modifiche, l'utilizzo del pulsante "Ripristina" può rendere molto più difficile.
FluffySamurai,

Risposte:


159

C'è una risposta migliore a questo problema, anche se potrei semplicemente scomporlo passo dopo passo.

Dovrai recuperare e verificare le ultime modifiche a monte in questo modo, ad esempio:

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

Dando un'occhiata al registro di commit, dovresti trovare qualcosa di simile a questo:

commit b76a5f1f5d3b323679e466a1a1d5f93c8828b269
Merge: 9271e6e a507888
Author: Tim Tom <tim@tom.com>
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 <john@doe.com>
Date:   Mon Apr 29 12:13:29 2013 +0000

    Add bar

commit 470ee0f407198057d5cb1d6427bb8371eab6157e
Author: John Doe <john@doe.com>
Date:   Mon Apr 29 10:29:10 2013 +0000

    Add foo

Ora vuoi ripristinare l'intera richiesta pull con la possibilità di ripristinare in seguito. Per fare ciò, dovrai prendere l'ID del commit unione .

Nell'esempio precedente, il commit di unione è quello in cui è indicato "Richiesta pull unita n. 123 ..." .

Fai questo per ripristinare entrambe le modifiche ( "Aggiungi barra" e "Aggiungi pippo" ) e finirai con un unico commit ripristinando l'intera richiesta pull che puoi ripristinare in seguito e mantenere pulita la cronologia delle modifiche:

git revert -m 1 b76a5f1f5d3b323679e466a1a1d5f93c8828b269

6
Questa dovrebbe essere la risposta corretta. C'è un riferimento nella pagina man di git-ripristina a maggiori dettagli dalla mailing list di git qui kernel.org/pub/software/scm/git/docs/howto/…
Justin Hamade

2
Perché il git checkout upstream/master -b revert/john/foo_and_bar? cosa fa esattamente?
Magne,

4
@Magne - stai creando un nuovo ramo in cui eseguire il ripristino, in cui puoi scegliere dove unire l'inversione. Fondamentalmente ti dà solo un maggiore controllo su cosa fare con il ramo. Nel mio caso, ho inviato una nuova richiesta pull da questo ramo "fisso" contenente la reversione al nostro ramo di sviluppo, il che significa che la mia nuova richiesta pull potrebbe anche essere ripristinata, se necessario. Questo è stato fatto per una versione in cui abbiamo deciso di estrarre la prima bozza di una funzione che è stata riprogrammata. Nessun codice errato, semplicemente non presente in questa versione.
Daniel Nalbach,

3
Ho imparato una dura lezione su questo. Abbiamo inserito una funzionalità nel nostro ramo di sviluppo, ma ci siamo resi conto che c'erano problemi con i dati e siamo tornati direttamente allo sviluppo. Più tardi, quando le cose furono sistemate, volevamo aggiungere nuove funzionalità di sviluppo a questo ramo per testare la loro compatibilità con questa funzione prima di eseguire il push, quindi ho unito lo sviluppo al ramo di funzionalità. Ciò ha anche applicato il commit di inversione, che ha annullato ogni modifica apportata al ramo della funzione. > <
Greg

86

Guarda il tuo grafico di commit (con gitk o un programma simile). Vedrai i commit dalla richiesta pull, vedrai i tuoi commit e un commit di merge (se non era un merge ad avanzamento rapido). Devi solo trovare l'ultimo dei tuoi commit prima dell'unione e reimpostare il ramo su questo commit.

(Se si dispone del reflog del ramo, dovrebbe essere ancora più facile trovare il commit prima dell'unione.)


(Modifica dopo ulteriori informazioni nei commenti :)

Bene, diamo un'occhiata al grafico:

screenshot 1

Presumo che l'ultimo commit (all'estrema destra) sia stata la tua unione sbagliata per richiesta pull , che ha unito la linea blu vista qui. Il tuo ultimo buon commit sarebbe quello precedente sulla linea nera, qui segnato in rosso:

inserisci qui la descrizione dell'immagine

Ripristina questo commit e dovresti andare bene.

Ciò significa che nella tua copia di lavoro locale esegui questa operazione (dopo esserti assicurato di non avere più contenuti non impegnati, ad esempio git stash):

git checkout master
git reset --hard 7a62674ba3df0853c63539175197a16122a739ef
gitk 

Ora conferma che sei davvero sul commit che ho segnato lì, e non vedrai nessuna delle cose estratte nei suoi antenati.

git push -f origin master

(se il tuo telecomando github è chiamato origin, altrimenti cambia il nome).

Ora anche tutto dovrebbe apparire su Github. I commit rimarranno comunque nel tuo repository, ma non raggiungibili da nessuna filiale, quindi non dovrebbero farti del male. (E saranno ancora sul repository di RogerPaladin, ovviamente.)

(Potrebbe esserci un modo specifico di Github solo web di fare la stessa cosa, ma non ho troppa familiarità con Github e il suo sistema di gestione delle richieste pull.)

Tieni presente che se qualcun altro ha già eseguito il pull del tuo master con un commit errato, ha lo stesso problema che hai attualmente e non può davvero contribuire. prima di ripristinare la nuova versione principale.

Se è probabile che ciò sia accaduto, o semplicemente vuoi evitare qualsiasi problema, usa il git revertcomando invece di git reset, per ripristinare le modifiche con un nuovo commit, invece di tornare a uno più vecchio. (Alcune persone pensano che non dovresti mai reimpostare con le filiali pubblicate.) Vedi altre risposte a questa domanda su come farlo.

Per il futuro:

Se desideri solo alcuni dei commit della filiale di RogerPaladin, prendi in considerazione l'utilizzo cherry-pickinvece di merge. Oppure comunica a RogerPaladin per spostarli in un ramo separato e inviare una nuova richiesta pull.


Ma abbiamo un sacco di impegni tra la fusione e il suo primo impegno. Quindi, come se avessimo il commit della fusione, i nostri commit e poi un altro commit da parte sua. Sembra che si sia fuso in impegni davvero vecchi.
Sarà il

Sì, si fonderà in tutto ciò che è un antenato del commit unito (e non già un antenato del tuo commit). Questo non dovrebbe impedirti di reimpostare: i commit non verranno riordinati da soli, se non hai effettuato un rebase in seguito.
Paŭlo Ebermann,

1
Sì, ora sembra giusto (a parte la strana fusione in se stesso - ma questo potrebbe essere un problema tecnico nel software del grafico di rete). :-) Sono felice di poterti aiutare.
Paŭlo Ebermann,

6
Penso che questo possa essere problematico se qualcuno ha eseguito i commit errati e in seguito ha inviato una richiesta pull che contiene gli stessi commit errati, quindi si intrufolano ma nel repository. Non sarebbe più sicuro creare un nuovo commit che inverta i cattivi commit? In questo modo se i cattivi commit sono stati tirati verso altri rami / forcelle, saranno effettivamente rimossi da un altro tiro verso quell'altro ramo / fork? Non lo sto affermando come un dato di fatto, questo è ciò che penso possa essere vero, essendo nella stessa posizione del PO e avendo trascorso circa un'ora considerando le mie opzioni.
Myles McDonnell il

4
@Vorrei suggerire di non accettare questa risposta. Questo va bene per il codice che non è stato ancora inviato (in questo caso, questa è una domanda SO più rilevante, ma per il codice che è condiviso pubblicamente, facendo un comando git che riscrive la storia (in questo caso, reset --harde un push forzato è pessima pratica.) La risposta di @errordeveloper di seguito mostra un modo per farlo senza riscrivere la storia o forzare la spinta
asmeurer,

34

Se il tiro era l'ultima cosa che ha fatto allora

git reset --hard HEAD~1

3
fai attenzione seguendo queste istruzioni, in realtà mi riporta indietro di 2 passi, non uno.
szeitlin,

1
@szeitlin Come è potuto accadere che ti abbia riportato indietro di 2 passaggi, non uno? So che questo commento è stato lasciato 4+ anni fa, ma sono curioso di sapere se qualcuno conosce una risposta su come potrebbe accadere. Questo è molto importante per me. Grazie.
Haradzieniec,

Non ricordo ora, ma suppongo che potrebbe accadere se avessi fatto un nuovo commit quando ho provato a ripristinare? Lo testerei con un repository fittizio se sei preoccupato.
szeitlin,

Questo ha funzionato bene per me. Ha eliminato la richiesta pull recentemente unita. Dopo git reset --hard HEAD~1, ho usato git push origin -fper aggiornare il repository remoto. Ma fai attenzione, presta attenzione prima di farlo.
Denis Oluka,

24

A partire dal 24 giugno 2014, puoi provare a cancellare facilmente un PR (Vedi " Ripristino di una richiesta pull ") con:

Presentazione del pulsante Ripristina

puoi facilmente ripristinare una richiesta pull su GitHub facendo clic su Ripristina:

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

Ti verrà richiesto di creare una nuova richiesta pull con le modifiche ripristinate:

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

Resta da testare, tuttavia, se tale ripristino utilizza -mo meno (anche per ripristinare le fusioni)

Ma Adil H Raza aggiunge nei commenti (dicembre 2019):

Questo è il comportamento previsto, ha creato un nuovo ramo e puoi creare un PR da questo nuovo ramo al tuo master.
In questo modo in futuro puoi annullare il ripristino del ripristino, se necessario, è l'opzione più sicura e non modificare direttamente il tuo master.


Attenzione : Korayem sottolinea nei commenti che:

Dopo un ripristino, supponiamo che tu abbia apportato ulteriori modifiche al ramo Git e creato un nuovo PR dallo stesso ramo di origine / destinazione.
Troverai che il PR mostra solo nuove modifiche, ma nulla di ciò che c'era prima di ripristinare .

Korayem ci fa riferimento a " Github: modifiche ignorate dopo il ripristino ( git cherry-pick, git rebase) " per ulteriori informazioni.


ho provato questo e ha creato un nuovo ramo invece di annullare PR sul master?
Грозный,

Strano. Potresti fare una nuova domanda per illustrare quel comportamento?
VonC

questo è il comportamento previsto, ha creato un nuovo ramo e puoi creare un PR da questo nuovo ramo al tuo master. In questo modo in futuro puoi annullare il ripristino del ripristino, se necessario, è l'opzione più sicura e non cambiare direttamente il tuo master.
Adil H. Raza,

1
@ AdilH.Raza Grazie. Ho incluso il tuo commento nella risposta per una maggiore visibilità.
VonC

1
@VonC incrocia le dita per salvare gli sviluppatori di tutto il mondo da troppa agonia e perdita di tempo
Korayem

8

Per annullare una richiesta pull di github con commit che non vuoi eliminare, devi eseguire un:

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

con l'hash di commit il commit PRIMA di unire la richiesta pull. Ciò rimuoverà tutti i commit dalla richiesta pull senza influenzare alcun commit all'interno della cronologia.

Un buon modo per trovare questo è quello di andare alla richiesta pull ora chiusa e trovare questo campo:

Immagine richiesta pull Immagine richiesta pull

Dopo aver eseguito il git reset, eseguire un:

git push origin --force <branch name>

Ciò dovrebbe ripristinare il ramo prima della richiesta pull senza influire su eventuali commit nel ramo inseriti nella cronologia dei commit tra commit dalla richiesta pull.

MODIFICARE:

Se si dovesse fare clic sul pulsante Ripristina sulla richiesta pull, questo crea un ulteriore commit sul ramo. NON decomprime o non si confonde. Ciò significa che se si preme il pulsante Ripristina, non è possibile aprire una nuova richiesta pull per aggiungere nuovamente tutto questo codice.


Ottimo modo per
chiarire le

Grazie! Era quello che stavo pianificando di fare, ma sarebbero stati circa 200 gli impegni da scegliere.
FluffySamurai,

1

Uso questo posto tutto il tempo, grazie.

Stavo cercando come annullare una richiesta pull e sono arrivato qui.

Stavo git reset --hardper "molto tempo fa" e fare un veloce ritorno indietro a dove ero prima di fare la richiesta pull.

Oltre a guardare qui, ho anche chiesto al mio collega cosa avrebbe fatto, e aveva una risposta generalmente buona: usando l'output di esempio nella prima risposta sopra:

git reset --hard 9271e6e

Come con la maggior parte delle cose in Git, se lo fai in un modo non facile, probabilmente stai sbagliando.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.