Come posso recuperare da un master di origine git push -f errato?


Risposte:


55

Git generalmente non butta via nulla, ma riprendersi da questo potrebbe essere ancora complicato.

Se hai la sorgente corretta, puoi semplicemente inserirla nel telecomando con l' --forceopzione. Git non avrà cancellato alcun ramo a meno che tu non glielo abbia detto. Se hai effettivamente perso dei commit, dai un'occhiata a questa guida utile per recuperare i commit . Se conosci lo SHA-1 dei commit che desideri, probabilmente stai bene.

La cosa migliore da fare: eseguire il backup di tutto e vedere cosa c'è ancora nel repository locale. Se possibile, fai lo stesso con il telecomando. Usa git fsckper vedere se riesci a recuperare le cose e soprattutto NON correregit gc .

Soprattutto, non usare mai l' --forceopzione a meno che tu non lo pensi davvero.


64
Molto probabilmente puoi semplicemente guardare i reflog per determinare dove erano originariamente i rami remoti. Ad esempio git reflog show remotes/origin/master,. Dovresti essere in grado di vedere la tua spinta lì dentro; il commit nella riga precedente è dov'era prima che lo incasinassi. Puoi quindi semplicemente spingere quella revisione (con --force) all'origine e tornare dove eri!
Cascabel

@ David: Oh. Non hai menzionato nella tua domanda che non avevi il repo. (Questo è ovviamente qualcosa che non vorresti mai fare.) Se hai accesso al filesystem da dove hai spinto, però, potresti comunque fare tutto questo lì.
Cascabel

1
@ David: Oddio. È sempre utile avere la directory corrente come parte del prompt per evitare questo genere di cose.
Cascabel

1
@Jefromi penso che quello che hai detto ci sia la risposta reale: anche con una vecchia versione (non avendo git fetcheditato da molto tempo) puoi visualizzare il reflog del lato di GitHub e recuperare!
nh2

1
Dov'è questa risposta di @Jefromi? Non vedo l'utente menzionato in questa pagina al di fuori di questo thread di commenti.
Don McCurdy

47

Se conosci l'hash del commit, è facile, basta ricreare il tuo ramo.

5794458...b459f069 master -> master (forced update)

Elimina il ramo remoto:

git push origin :master

quindi ricrea il tuo ramo con i seguenti comandi:

git checkout 5794458
git branch master
git push origin master

28

La soluzione è già menzionata qui

# work on local master
git checkout master

# reset to the previous state of origin/master, as recorded by reflog
git reset --hard origin/master@{1}

# at this point verify that this is indeed the desired commit.
# (if necessary, use git reflog to find the right one, and
# git reset --hard to that one)

# finally, push the master branch (and only the master branch) to the server
git push -f origin master

Grazie, questo ha funzionato per me. Non avevo accesso per eliminare il master quindi il commento approvato non è riuscito.
Andi

Sì, e git reflog show remotes/origin/masterse è necessario git reflog (come menzionato da @Cascabel sopra)
Josiah Yoder

2
Questa è la risposta corretta, grazie per esserti collegato a quella corretta.
Noitidart

6

Se non ti trovi in ​​quel repo locale da cui proviene il push forzato, a livello origin / master non c'è modo di recuperare. Ma se sei abbastanza fortunato da usare GitHub o GitHub for Enterprise , puoi dare un'occhiata all'API REST e recuperare il commit perso come patch, ad esempio:

  1. Elenca gli eventi e trova il formato lungo del commit sha1

https://api.github.com/repos/apache/logging-log4j2/events

  1. Scarica il commit perso e recupera la relativa patch nel percorso json .files [] / patch

https://api.github.com/repos/apache/logging-log4j2/commits/889232e28f3863d2a17392c06c1dd8cac68485de

  1. Applicare localmente e spingere di nuovo

git apply patch.patch && git commit -m "commit ripristinato" && git push origin master


4

Un altro modo per recuperare il commit perso o anche per capire quali commit sono stati persi, se il push precedente non proveniva dal tuo repository locale, è guardare la tua macchina CI.

Se hai un lavoro che testa il ramo master dopo ogni commit (o una serie di commit consecutivi), che dovresti avere, puoi dare un'occhiata a cosa stava testando per ultimo. Questo è il commit che devi ripristinare.

La macchina CI potrebbe persino mantenere un clone locale del repository, da cui potresti essere in grado di eseguire questo ripristino.

Fonte: probabilmente fornitura continua: versioni software affidabili tramite build, test e automazione della distribuzione (Addison-Wesley Signature Series (Fowler))


3

Sì, puoi recuperare i commit dopo git push -f your_branch

Testo da Doc :

Elimina le voci più vecchie del tempo specificato. Se questa opzione non è specificata, l'ora di scadenza viene presa dall'impostazione di configurazione gc.reflogExpire, che a sua volta ha un valore predefinito di 90 giorni. --expire = tutte le voci eliminano indipendentemente dalla loro età; --expire = non disattiva mai l'eliminazione delle voci raggiungibili (ma vedi --expire-unreachable).

Quindi puoi fare:

1- git reflog

inserisci qui la descrizione dell'immagine

2- scegli Head_Number con cui vuoi recuperare git reset –hard HEAD@{HEAD-NUMBER}

inserisci qui la descrizione dell'immagine

3- puoi vedere tutti i commit su questa testa da git cherry -v branch_name

4- alla fine dovresti forzare la spinta git push -f branch_name

O

1- ottieni il numero di SHA dal tuo client GIT (interfaccia)

git reset --hard commit_SHA

2- forza di spinta

git push -f your_branch

Spero che sia di aiuto


2

Ho fatto la stessa cosa annullando l'ultima spinta per un solo file. Finito per tornare allo stato originale del repository. Stavo usando i comandi git di Linus poiché avevo la copia locale su Linux. Per fortuna quella copia era ancora intatta.

Tutto quello che ho fatto è stato (dopo aver freneticamente fatto qualche altra copia del repo locale):

git add .
git status

(diceva che origin / master era in vantaggio di 68 commit, bene ... quelli erano tutti i commit che ho cancellato)

git remote set-url origin <GIT_SSH_URL>
git push

E tutto è stato ripristinato com'era prima che spingessi con forza. La cosa più importante da ricordare è non fare mai un checkout con git. dopo aver spinto con forza. Ma la migliore pratica è disabilitare l'opzione push. Non lo userò mai più. Ho imparato la lezione !!


1

Per le persone in situazioni davvero brutte come me (ad esempio, se ricevi bad objecterrori durante l'esecuzionegit reset --hard ):

Ho scritto uno script chiamato treesaver che estrae tutti i tuoi file dall'API GitHub come ultima risorsa. Ecco come usarlo:

  1. Clona lo treesaverscript ecd ad esso.
  2. Trova la SHAstringa dell'albero che desideri ripristinare accedendo https://api.github.com/repos/<your_username_or_org>/<repo>/events .
  3. Nella payloadproprietà corrispondente al tuo evento push, trova l' commitelemento a cui desideri tornare e fai clic su di esso url.
  4. Sotto commit.tree, copia il file tree's url.
  5. Corri python3 main.py <tree_url> <path_to_save_to>.

Ad esempio, nel mio caso, eseguirò:

python3 main.py https://api.github.com/repos/anthonykrivonos/my-repo/git/trees/1234567 .

Naturalmente, i PR sono i benvenuti.


0

Qui puoi leggere le decisioni https://evilmartians.com/chronicles/git-push---force-and-how-to-deal-with-it

Il secondo mi ha aiutato. Ho sbagliato questi comandi

1) (some-branch) git pull -> correct command was git pull origin some-branch

2) (some-branch) git push -f origin some-branch

Dopo questi comandi ho perso tre commit. Per recuperarli ho guardato al terminale dove ho fatto erroneamente 'git pull' e ho visto l'output simile

60223bf ... 0b258eb qualche ramo -> origine / qualche ramo

Il secondo hash 0b258eb era esattamente quello di cui avevo bisogno. Quindi, ho preso questo hash e ho prodotto il comando

git push --force origin 0b258eb:some-branch
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.