Annullare una 'spinta git'


592

Ecco cosa ho fatto sul mio ramo presumibilmente stabile ...

% git rebase master
First, rewinding head to replay your work on top of it...
Fast-forwarded alpha-0.3.0 to master.
% git status
# On branch alpha-0.3.0
# Your branch is ahead of 'origin/alpha-0.3.0' by 53 commits.
#
nothing to commit (working directory clean)
% git push
Fetching remote heads...
  refs/
  refs/heads/
  refs/tags/
  refs/remotes/
'refs/heads/master': up-to-date
updating 'refs/heads/alpha-0.3.0'
  from cc4b63bebb6e6dd04407f8788938244b78c50285
  to   83c9191dea88d146400853af5eb7555f252001b0
    done
'refs/heads/unstable': up-to-date
Updating remote server info

È stato tutto un errore, come ho capito in seguito. Vorrei annullare l'intero processo e ripristinare il ramo alpha-0.3.0 a quello che era.

Cosa dovrei fare?



4
Non è proprio la stessa situazione, l'annullamento di un rebase è uno scenario di repository locale, l'annullamento di una git push comporta un repository remoto e può essere più complicato a seconda dell'accesso che hai.
CB Bailey,

Steen - hai ragione - probabilmente avrei dovuto supporre. Ho pensato che il repository benedetto da cui tutti attingono sia più un'attività di amministrazione e quindi appartiene qui, dove git lato client generale è una domanda stackoverflow.
Ciro,

Chiarimento rapido - Immagino che se ti riferisci a un commit git con un valore hash parziale , git supporrà che stai parlando del commit il cui hash inizia con quella stringa?
Gershom,

Risposte:


944

È necessario assicurarsi che nessun altro utente di questo repository stia recuperando le modifiche errate o che stia tentando di basarsi sui commit che si desidera rimuovere perché si sta per riavvolgere la cronologia.

Quindi è necessario 'forzare' spingere il vecchio riferimento.

git push -f origin last_known_good_commit:branch_name

o nel tuo caso

git push -f origin cc4b63bebb6:alpha-0.3.0

Potrebbe essere stato receive.denyNonFastForwardsimpostato sul repository remoto. In questo caso, verrà visualizzato un errore che include la frase [remote rejected].

In questo scenario, dovrai eliminare e ricreare il ramo.

git push origin :alpha-0.3.0
git push origin cc4b63bebb6:refs/heads/alpha-0.3.0

Se questo non funziona, forse perché hai receive.denyDeletesimpostato, devi avere accesso diretto al repository. Nel repository remoto, devi fare qualcosa come il seguente comando idraulico.

git update-ref refs/heads/alpha-0.3.0 cc4b63bebb6 83c9191dea8

16
Una risposta perfetta e ben spiegata - grazie mille. Per chiunque altro si imbattesse in questo, per motivi accademici ho provato entrambi i primi 2 approcci, ed entrambi hanno funzionato - ovviamente se il primo funziona, è l'approccio più pulito. Se ti chiassi 10 volte Charles, lo farei. :)
Ciro,

139
Per una rapida git push -f origin last_known_good_commit:branch_name
consultazione

5
git push -f origine cc4b63bebb6: alpha-0.3.0 => questo mi ha aiutato, Nota alpha-0.3.0 è il nome della diramazione e cc4b63bebb6 è l'id del commit a cui vogliamo ripristinare. quindi, dopo aver eseguito questo comando saremo in cc4b63bebb6 commit id.
Kumar,

22
Questa soluzione è estremamente pericolosa se si lavora in un repository condiviso. Come best practice, tutti gli commit inviati a un repository remoto condiviso devono essere considerati "immutabili". Usa invece 'git revert': kernel.org/pub/software/scm/git/docs/…
Saboosh

1
jww - rispetto a tutto il resto, git è lo strumento di controllo del codice sorgente più ricco di funzionalità ed efficiente disponibile. Ogni squadra lo usa in modo diverso. Vale la pena trascorrere un fine settimana giocando con un repository nuovo e attraversando tutti gli scenari comuni. Dopo aver trascorso un po 'di tempo a lavorarci, lo sviluppo è molto meno stressante.
user1491819,

165

Credo che tu possa fare anche questo:

git checkout alpha-0.3.0
git reset --hard cc4b63bebb6
git push origin +alpha-0.3.0

Questo è molto simile all'ultimo metodo, tranne per il fatto che non è necessario spostarsi nel repository remoto.


9
Questo ha funzionato anche per me, ma vale la pena notare che questo "riscriverà" la storia sul telecomando. Questo potrebbe essere quello che vuoi, ma potrebbe non esserlo!
Tom,

3
+1 per questa risposta che mi ha davvero aiutato. Volevo anche aggiungere (e chiarire le cose) che l'ID commit (che viene dopo il --hardparametro " ") dovrebbe essere l'ID di qualsiasi commit a cui vuoi reimpostare il tuo ramo.
Michael Dautermann,

1
Riscritta bene la storia ... chiunque potesse aver apportato le modifiche, mi sono appena assicurato che lo facessero, git reset --hard [commit_id]quindi non abbiamo fatto confusione con il continuum spazio-temporale.
Alien Life Form

9
A cosa serve + in "git push origin + alpha-0.3.0"?
jpierson,

1
@jpierson +impone che la spinta avvenga, in modo simile a -f(ma leggermente diverso: stackoverflow.com/a/25937833/1757149 ). Senza di essa, se si tenta git push origin alpha-0.3.0la spinta fallirà: Updates were rejected because the tip of your current branch is behind.
A__

106

git revert è meno pericoloso di alcuni degli approcci suggeriti qui:

prompt> git revert 35f6af6f77f116ef922e3d75bc80a4a466f92650
[master 71738a9] Revert "Issue #482 - Fixed bug."
 4 files changed, 30 insertions(+), 42 deletions(-)
prompt> git status
# On branch master
# Your branch is ahead of 'origin/master' by 1 commit.
#
nothing to commit (working directory clean)
prompt>

Sostituisci 35f6af6f77f116ef922e3d75bc80a4a466f92650 con il tuo commit.


2
Come faccio a trovare l'ID 35f6af6f77f116ef922e3d75bc80a4a466f92650? Questa risposta sarebbe migliore se tu potessi spiegarlo.
Volomike,

2
@Volomike (e gli sviluppatori googling del futuro), questa domanda descrive molti modi per ottenerlo: controllo della versione e domanda hash su SO
Jaime,

Questa è la risposta giusta, perché con "git reset" non dovresti essere in grado di spingere (gli aggiornamenti sono stati respinti perché la punta del tuo ramo attuale è dietro la sua controparte remota) o devi forzare il pull che non è davvero pulito.
Thomas Decaux,

Questo stava funzionando per me. Tuttavia, fai attenzione poiché ripristina ripristinerà tutte le modifiche nei tuoi file locali.
user1941537

Ho optato per questo approccio più volte, ma utilizzo anche git rebase -i <id-before-last-good-commit> per fare un rebase interattivo e ripulire la cronologia come suggerito qui, stackoverflow.com/questions/5189560/… .
Ernesto Allely,

35

La soluzione accettata (da @charles bailey) è estremamente pericolosa se si lavora in un repository condiviso.

Come best practice, tutti gli commit inviati a un repository remoto condiviso devono essere considerati "immutabili". Utilizzare invece 'git revert': http://www.kernel.org/pub/software/scm/git/docs/user-manual.html#fixing-mistakes

https://git-scm.com/book/be/v2/Git-Basics-Undoing-Things


Quali sono esattamente le istruzioni che stai prescrivendo? Sembra che tu abbia solo vecchi link.
JWW

32

Un modo per farlo senza perdere le modifiche che volevi:

git reset cc4b63b 
git stash
git push -f origin alpha-0.3.0
git stash pop

Quindi puoi scegliere i file che intendevi inviare


19

Un altro modo per farlo:

  1. crea un altro ramo
  2. controlla il commit precedente su quel ramo usando "git checkout"
  3. spingere il nuovo ramo.
  4. elimina il vecchio ramo e premi elimina (usa git push origin --delete <branch_name>)
  5. rinominare il nuovo ramo nel vecchio ramo
  6. spingere di nuovo.

2
Questa sembra una vera soluzione quando hai già commesso errori nei repo
Illarion Kovalchuk


11

Annulla più commit git reset --hard 0ad5a7a6 (Fornisci solo hash SHA1 commit)

Annulla l'ultimo commit

git reset --hard HEAD ~ 1 (le modifiche all'ultimo commit saranno rimosse) git reset --soft HEAD ~ 1 (le modifiche all'ultimo commit saranno disponibili come modifiche locali senza commit)


9

Scenario 1 : se si desidera annullare l'ultimo commit, pronunciare 8123b7e04b3, di seguito è riportato il comando (ha funzionato per me):

git push origin +8123b7e04b3^:<branch_name>

L'output è simile al seguente:

Total 0 (delta 0), reused 0 (delta 0)
To https://testlocation/code.git
 + 8123b7e...92bc500 8123b7e04b3^ -> master (forced update)

Informazioni aggiuntive: Scenario 2 : in alcune situazioni, potresti voler ripristinare ciò che hai appena annullato (sostanzialmente annullare l'annullamento) tramite il comando precedente, quindi utilizzare il comando seguente:

git reset --hard 8123b7e04b3

Produzione:

HEAD is now at cc6206c Comment_that_was_entered_for_commit

Maggiori informazioni qui: https://github.com/blog/2019-how-to-undo-almost-anything-with-git


Lo scenario 1 dovrebbe essere la risposta accettata poiché la domanda non ha specificato quale commit eliminare. La risposta accettata cancella solo l' ultimo commit. Questa risposta elimina qualsiasi commit.
Domenico Cerisano,

0

Le risposte esistenti sono buone e corrette, tuttavia cosa succede se è necessario annullare il pushma:

  1. Vuoi mantenere i commit a livello locale o vuoi mantenere le modifiche senza commit
  2. Non sai quanti impegni hai appena spinto

Utilizzare questo comando per ripristinare la modifica in ref:

git push -f origin refs/remotes/origin/<branch>@{1}:<branch>

-2

Se vuoi ignorare l'ultimo commit che hai appena inserito nel ramo remoto: questo non rimuoverà il commit ma lo ignorerà semplicemente spostando il puntatore git su quello precedente, a cui fa riferimento HEAD ^ o HEAD ^ 1

git push origin +HEAD^:branch

Ma se hai già spinto questo commit e altri hanno tirato il ramo. In questo caso, riscrivere la cronologia della tua filiale non è desiderabile e dovresti invece ripristinare questo commit:

git revert <SHA-1>
git push origin branch

1
sì! questo ha funzionato come un incantesimo quando si lavora con github. Grazie.
cukabeka,

La domanda riguarda "push", quindi riguarda il ramo remoto. No per spostare la TESTA su un commit, il che significa ignorare l'ultimo commit spinto, basta fare questo: git push origin + HEAD ^: your_branch
mkebri
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.