Ripristino remoto di un determinato commit


709

Voglio annullare tutte le modifiche apportate dopo il commit <commit-hash>. Così ho fatto:

git reset --hard <commit-hash>

Ora voglio fare lo stesso con il mio telecomando. Come posso fare questo? Ho fatto alcuni commit (e push) dopo <commit-hash>e voglio solo scartarli tutti. È solo qualcosa che è andato terribilmente storto e non voglio peggiorare quanto non lo è già. ; (

Io fondamentalmente voglio per riavvolgere la mia origin/mastera<commit-hash>


3
Sei sicuro di origin/masternon essere stato attirato e spinto da altri utenti? La modifica della cronologia di un repository pubblico (ovvero non locale) è qualcosa che si desidera evitare in ogni momento.
vindia,

Risposte:


1252

Supponendo che il tuo ramo sia chiamato mastersia qui che da remoto, e che il tuo telecomando sia chiamato originpotresti fare:

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

Tuttavia, dovresti evitare di farlo se qualcun altro sta lavorando con il tuo repository remoto e ha apportato le modifiche. In tal caso, sarebbe meglio ripristinare le commit non desiderate, quindi spingere normalmente.

Aggiornamento: di seguito hai spiegato che altre persone hanno apportato le modifiche che hai inviato, quindi è meglio creare un nuovo commit che ripristini tutte quelle modifiche . C'è una bella spiegazione delle tue opzioni per farlo in questa risposta di Jakub Narębski . Quale è il più conveniente dipende da quanti commit vuoi ripristinare e quale metodo ha più senso per te.

Dal momento che dalla tua domanda è chiaro che hai già usato git reset --hardper ripristinare il tuo masterramo, potresti dover iniziare usando git reset --hard ORIG_HEADper spostare il tuo ramo dove era prima. (Come sempre git reset --hard, assicurati che git statussia pulito, di essere sul ramo giusto e di essere a conoscenza git reflogcome uno strumento per recuperare i commit apparentemente persi.) Dovresti anche controllare che ORIG_HEADpunti al commit giusto, con git show ORIG_HEAD.

Risoluzione dei problemi:

Se viene visualizzato un messaggio del tipo " ! [Telecomando rifiutato] a60f7d85 -> master (hook di pre-ricezione rifiutato) "

quindi è necessario consentire la riscrittura della cronologia del ramo per il ramo specifico. In BitBucket, ad esempio, diceva "Non è consentita la riscrittura della cronologia dei rami". C'è una casella di controllo Allow rewriting branch historyche devi selezionare.


21
Pericolo: questo ripristino presuppone che il ramo ( tracciamento ) corrispondente sia attualmente estratto e che non ci siano modifiche non confermate che si desidera mantenere. Usa git update-refinvece direset --hard ; ti permetterà di fare lo stesso senza avere un albero funzionante / ramo
estratto

3
Vedo. È stato spinto e cambiato da altri. Quindi dovrei usare revert ma diciamo che voglio ripristinare i 4 commit precedenti, quindi dovrei fare git revert comit1; git push; git revert comit2; git push; ...o semplicemente git revert commit4; git push?
nacho4d,

1
@ nacho4d: non è necessario spingere dopo ogni ripristino - c'è una bella descrizione di cosa fare in questa risposta di Jakub Narębski . È necessario ripristinare ciascun commit procedendo all'indietro - semplicemente facendo si git revert commit4crea un nuovo commit che annulla solo le modifiche introdotte commit4. Come la risposta che ho collegato a sottolineare, tuttavia, è possibile raggrupparli in un unico commit.
Mark Longair,

1
@Mark Ho già eseguito git reset --hardma ho eliminato il mio locale e rimosso nuovamente dall'origine, quindi posso fare il git revert ...mio dubbio ora è: devo ripristinare ogni commit e push (uno per uno) o semplicemente ripristinare il primo commit dopo il giusto impegno?
nacho4d,

1
@sehe: è difficile da usare perché è necessario utilizzare il nome di riferimento completo, quindi è facile per le persone sporcare la propria .gitdirectory con riferimenti che non intendevano creare. Ho sbagliato a dire che non ci sono controlli di sicurezza, però. Puoi trovare la classificazione nei comandi "idraulica" e "porcellana" nella pagina man di git .
Mark Longair,

123

Usa le altre risposte se non ti dispiace perdere le modifiche locali. Questo metodo può comunque rovinare il telecomando se si sceglie l'hash di commit errato su cui tornare.

Se vuoi solo fare del match match remoto un commit che è ovunque nel tuo repository locale:

  1. Do Non fare alcun azzeramento.
  2. Utilizzare git logper trovare il commit a cui si desidera che il telecomando si trovi. git log -pper vedere le modifiche o git log --graph --all --oneline --decorateper vedere un albero compatto.
  3. Copia l'hash del commit o il suo tag o il nome del suo ramo se è la punta.
  4. Esegui un comando come:

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

    per esempio

    git push --force origin 606fdfaa33af1844c86f4267a136d4666e576cdc:master
    

    o

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

Uso un comodo alias ( git go) per visualizzare la cronologia come nel passaggio 2, che può essere aggiunto in questo modo:

    git config --global alias.go 'log --graph --all --decorate --oneline'`

3
Il grafico è stato un bel suggerimento, ho appena aggiunto -5 per ottenere solo gli ultimi n commit, era un altro enorme albero. Anche evitare il ripristino è proprio quello che stavo cercando. Fantastico
AlexanderD

@AlexanderD Puoi anche aggiungere l'alias a Git piuttosto che alla tua shell, quindi funziona ovunque. Git comprende quegli alias e i tab-complet dal comando completo in modo da poter aggiungere argomenti. git config --global alias.graph 'log --graph --all --decorate --oneline'è meno disordinato e puoi ancora limitarlo, ad esempio:git graph -5
Walf

Questo è perfetto. Ho sempre confuso il mio locale. Era esattamente quello di cui avevo bisogno dopo aver spinto accidentalmente la mia messa in scena per vivere :( Grazie!
Jake,

1
Su Windows, immettere qper uscire dal registro git. 2 minuti non tornerò mai più.
dst3p,

1
@ dst3p È su ogni piattaforma, amico. Il programma cercapersone è in genere lessed qè il modo normale di uscire. Git Bash è come un terminale * nix.
Walf

63

Ho risolto un problema come il tuo con questi comandi:

git reset --hard <commit-hash> 
git push -f <remote> <local branch>:<remote branch> 

13

Su GitLab, potresti dover impostare il tuo ramo su non protetto prima di farlo. È possibile farlo in [repository]> Impostazioni> Repository> Branch protetti. Quindi il metodo dalla risposta di Mark funziona.

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

10

Se vuoi una versione precedente del file, ti consiglio di usare git checkout.

git checkout <commit-hash>

In questo modo ti rimanderai indietro nel tempo, non influisce sullo stato corrente del tuo progetto, puoi venire alla mainline git checkout mainline

ma quando aggiungi un file nell'argomento, quel file ti viene riportato da una volta precedente all'ora del tuo progetto attuale, cioè il tuo progetto attuale viene cambiato e deve essere impegnato.

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

Il vantaggio di ciò è che non elimina la cronologia e non ripristina le modifiche di un determinato codice (git revert)

Scopri di più qui https://www.atlassian.com/git/tutorials/undoing-changes#git-checkout


Questa è una risposta eccellente: funziona, è periodicamente ed è molto sicura; se sbagli è facile tornare indietro.
bob

8

I miei due centesimi alle risposte precedenti: se

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

continua a non funzionare, potresti voler modificare <your-remote-repo>.git/configla sezione di ricezione del file:

[receive]
  #denyNonFastforwards = true
  denyNonFastforwards = false

È utile sapere come configurare un telecomando per consentire push non rapidi poiché la maggior parte delle risposte sembra assumere un servizio remoto come github o bitbucket.
strongbutgood

2

Se la tua filiale non è sviluppo o produzione, il modo più semplice per raggiungere questo obiettivo è reimpostare un certo commit localmente e creare una nuova filiale da lì. Puoi usare:

git checkout 000000

(dove 000000 è l'id commit dove vuoi andare) nel tuo ramo problematico e quindi semplicemente crea un nuovo ramo:

git remote add [name_of_your_remote]

Quindi puoi creare un nuovo PR e tutto funzionerà bene!


1

Fai una cosa, ottieni lo SHA del commit n. come 87c9808 e quindi,

  1. muoviti, cioè la tua testa al commit specificato (facendo git reset --hard 89cef43 // menziona il tuo numero qui)
  2. Quindi fai alcune modifiche in un file casuale, in modo che git ti chieda di eseguire il commit a livello locale e quindi in remoto. Pertanto, ciò che devi fare ora è. dopo aver applicato change git commit -a -m "commit commit"
  3. Ora invia il seguente commit (se questo è stato eseguito in locale) da git push origin master
  4. Quello che ti chiederà Git è quello

errore: impossibile inviare alcuni riferimenti a ' https://github.com/YOURREPOSITORY/AndroidExperiments.git ' suggerimento: gli aggiornamenti sono stati rifiutati perché la punta del ramo corrente è dietro suggerimento: la sua controparte remota. Integra le modifiche remote (es. Suggerimento: 'git pull ...') prima di premere di nuovo. **

  1. Quindi ora quello che puoi fare è

git push --force origin master

  1. E quindi, spero che funzioni :)

1

Sourcetree: reimpostazione remota su un determinato commit

  1. Se hai inviato un commit errato sul tuo telecomando (origin / feature / 1337_MyAwesomeFeature) come sotto l'immagine

Vai a Telecomandi

  1. Vai a Telecomandi> origine> funzione> 1337_MyAwesomeFeature
  2. Fare clic con il tasto destro del mouse e selezionare "Elimina origine / funzione / 1337_MyAwesomeFeature" (oppure modificarne il nome se si desidera un backup e saltare il passaggio 4.)
  3. Fai clic su "Forza eliminazione" e "OK".

inserisci qui la descrizione dell'immagine inserisci qui la descrizione dell'immagine

  1. Seleziona il commit precedente e scegli "Ripristina ramo corrente su questo commit"
  2. Scegli quale modalità vuoi avere (Difficile se non vuoi le ultime modifiche) e "OK".

inserisci qui la descrizione dell'immagine inserisci qui la descrizione dell'immagine

  1. Invia questo commit a una nuova origine / funzione / 1337_MyAwesomeFeature inserisci qui la descrizione dell'immagine

  2. Il ramo di funzionalità locale e il ramo di funzionalità remoto sono ora sul commit precedente (di tua scelta) inserisci qui la descrizione dell'immagine

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.