Come ripristinare un repository Git su un commit precedente

Come faccio a tornare dal mio stato attuale a uno scatto fatto su un certo commit?

Se faccio git log , ottengo il seguente risultato:

 $ git log commit a867b4af366350be2e7c21b8de9cc6504678a61b` Author: Me  Date: Thu Nov 4 18:59:41 2010 -0400 blah blah blah... commit 25eee4caef46ae64aa08e8ab3f988bc917ee1ce4 Author: Me  Date: Thu Nov 4 05:13:39 2010 -0400 more blah blah blah... commit 0766c053c0ea2035e90f504928f8df3c9363b8bd Author: Me  Date: Thu Nov 4 00:55:06 2010 -0400 And yet more blah blah... commit 0d1d7fc32e5a947fbd92ee598033d85bfc445a50 Author: Me  Date: Wed Nov 3 23:56:08 2010 -0400 Yep, more blah blah. 

Come ripristinare il commit dal 3 novembre, ovvero commit 0d1d7fc ?

Questo dipende molto da cosa intendi per “ripristino”.

Passa temporaneamente a un commit diverso

Se vuoi tornare temporaneamente ad esso, giocare, poi tornare dove sei, tutto quello che devi fare è dare un’occhiata al commit desiderato:

 # This will detach your HEAD, that is, leave you with no branch checked out: git checkout 0d1d7fc32 

O se vuoi fare dei commit mentre sei lì, vai avanti e crea un nuovo ramo mentre ci sei:

 git checkout -b old-state 0d1d7fc32 

Per tornare al punto in cui ti trovavi, controlla il ramo su cui eri di nuovo. (Se hai apportato delle modifiche, come sempre quando cambi succursali, dovrai gestirle a seconda dei casi.Potresti reimpostarle per buttarle via, potresti mettere da parte, prelevare, ripulire pop per portarle con te, potresti commettere li a un ramo lì se vuoi un ramo lì.)

Elimina duramente commit non pubblicati

Se, d’altra parte, vuoi davvero sbarazzarti di tutto ciò che hai fatto da allora, ci sono due possibilità. Uno, se non hai pubblicato nessuno di questi commit, resetta semplicemente:

 # This will destroy any local modifications. # Don't do it if you have uncommitted work you want to keep. git reset --hard 0d1d7fc32 # Alternatively, if there's work to keep: git stash git reset --hard 0d1d7fc32 git stash pop # This saves the modifications, then reapplies that patch after resetting. # You could get merge conflicts, if you've modified things which were # changed since the commit you reset to. 

Se ti incasini, hai già buttato via le tue modifiche locali, ma puoi almeno tornare al punto in cui ti trovavi prima reimpostando di nuovo.

Annulla i commit pubblicati con nuovi commit

D’altra parte, se hai pubblicato il lavoro, probabilmente non vuoi reimpostare il ramo, dal momento che è effettivamente riscrivere la cronologia. In tal caso, potresti davvero annullare i commit. Con Git, il ripristino ha un significato molto specifico: crea un commit con la patch inversa per cancellarlo. In questo modo non riscrivi alcuna cronologia.

 # This will create three separate revert commits: git revert a867b4af 25eee4ca 0766c053 # It also takes ranges. This will revert the last two commits: git revert HEAD~2..HEAD #Similarly, you can revert a range of commits using commit hashes: git revert a867b4af..0766c053 # Reverting a merge commit git revert -m 1  # To get just one, you could use `rebase -i` to squash them afterwards # Or, you could do it manually (be sure to do this at top level of the repo) # get your index and work tree into the desired state, without changing HEAD: git checkout 0d1d7fc32 . # Then commit. Be sure and write a good message describing what you just did git commit 

La manpage git-revert realtà copre molto di questo nella sua descrizione. Un altro link utile è questa sezione git-scm.com che discute di git-revert .

Se decidi di non voler tornare, dopotutto, puoi ripristinare il ripristino (come descritto qui) o ripristinare prima del ripristino (vedi la sezione precedente).

Potresti trovare questa risposta utile anche in questo caso:
Come spostare HEAD in una posizione precedente? (Testa staccata)

Ripristino della copia di lavoro in commit più recente

Per ripristinare un commit precedente, ignorando eventuali modifiche:

 git reset --hard HEAD 

dove HEAD è l’ultimo commit nel tuo attuale ramo

Ripristino della copia di lavoro in un commit precedente

Per ripristinare un commit più vecchio del commit più recente:

 # Resets index to formsr commit; replace '56e05fced' with your commit code git reset 56e05fced # Moves pointer back to previous HEAD git reset --soft [email protected]{1} git commit -m "Revert to 56e05fced" # Updates working copy to reflect the new commit git reset --hard 

I crediti vanno a una domanda simile di Stack Overflow, Ripristina un commit da un hash SHA in Git? .

Molte risposte complicate e pericolose qui, ma in realtà è facile:

 git revert --no-commit 0766c053..HEAD git commit 

Questo ripristinerà tutto dall’HEAD all’hash di commit, il che significa che ricreerà lo stato di commit nell’albero di lavoro come se ogni commit fosse tornato indietro. È quindi ansible impegnare l’albero corrente e creerà un nuovo commit essenzialmente equivalente al commit “ripristinato”.

(Il flag --no-commit consente a git di annullare tutti i commit in una volta, altrimenti ti verrà richiesto un messaggio per ogni commit nell’intervallo, sporcando la cronologia con nuovi commit non necessari.)

Questo è un modo semplice e sicuro per ripristinare uno stato precedente . Nessuna storia viene distrutta, quindi può essere utilizzata per i commit che sono già stati resi pubblici.

L’opzione migliore per me e probabilmente altri è l’opzione di ripristino Git:

 git reset --hard  && git clean -f 

Questa è stata l’opzione migliore per me! È semplice, veloce ed efficace!


Nota: come menzionato nei commenti, non farlo se condividi il tuo ramo con altre persone che hanno copie dei vecchi commit

Anche dai commenti, se volessi usare un metodo meno “ballzy”

git clean -i

Prima di rispondere aggiungiamo un po ‘di background, spiegando cos’è questo HEAD .

First of all what is HEAD?

HEAD è semplicemente un riferimento al commit corrente (più recente) sul ramo corrente. Può esserci un solo HEAD in qualsiasi momento (escluso l’ git worktree ).

Il contenuto di HEAD è memorizzato all’interno di .git/HEAD e contiene i 40 byte SHA-1 del commit corrente.


detached HEAD

Se non si è sul commit più recente – significa che HEAD punta a un commit precedente nella cronologia è chiamato detached HEAD .

Inserisci qui la descrizione dell'immagine

Sulla riga di comando sarà simile a questo: SHA-1 invece del nome del ramo poiché HEAD non punta al tip del ramo corrente:

Inserisci qui la descrizione dell'immagine


Alcune opzioni su come recuperare da un HEAD distaccato:


git checkout

 git checkout  git checkout -b   git checkout HEAD~X // x is the number of commits t go back 

Questo controllerà il nuovo ramo che punta al commit desiderato. Questo comando eseguirà il checkout su un dato commit.

A questo punto puoi creare un ramo e iniziare a lavorare da questo punto in poi:

 # Checkout a given commit. # Doing so will result in a `detached HEAD` which mean that the `HEAD` # is not pointing to the latest so you will need to checkout branch # in order to be able to update the code. git checkout  # Create a new branch forked to the given commit git checkout -b  

git reflog

Puoi sempre usare anche il reflog . git reflog visualizzerà tutte le modifiche che hanno aggiornato l’ HEAD e verificando la voce di reflog desiderata imposterà il HEAD su questo commit.

Ogni volta che l’HEAD viene modificato ci sarà una nuova voce nel reflog

 git reflog git checkout [email protected]{...} 

Questo ti riporterà al commit desiderato

Inserisci qui la descrizione dell'immagine


git reset HEAD --hard

“Sposta” la testa indietro al commit desiderato.

 # This will destroy any local modifications. # Don't do it if you have uncommitted work you want to keep. git reset --hard 0d1d7fc32 # Alternatively, if there's work to keep: git stash git reset --hard 0d1d7fc32 git stash pop # This saves the modifications, then reapplies that patch after resetting. # You could get merge conflicts, if you've modified things which were # changed since the commit you reset to. 
  • Nota: ( A partire da Git 2.7 ) puoi usare anche git rebase --no-autostash .

Questo schema illustra quale comando fa cosa. Come puoi vedere, il reset && checkout modificano l’ HEAD .

Inserisci qui la descrizione dell'immagine

Se vuoi “uncommit”, cancella l’ultimo messaggio di commit e rimetti i file modificati nella staging, dovresti usare il comando:

 git reset --soft HEAD~1 
  • --soft indica che i file non salvati dovrebbero essere mantenuti come file di lavoro opposti a --hard che li eliminerebbe.
  • HEAD~1 è l’ultimo commit. Se si desidera eseguire il rollback di 3 commit, è ansible utilizzare HEAD~3 . Se si desidera eseguire il rollback a un numero di revisione specifico, è ansible farlo utilizzando l’hash SHA.

Questo è un comando estremamente utile in situazioni in cui hai commesso la cosa sbagliata e vuoi annullare quell’ultimo commit.

Fonte: http://nakkaya.com/2009/09/24/git-delete-last-commit/

Ho provato un sacco di modi per ripristinare le modifiche locali in Git, e sembra che funzioni meglio se si desidera ripristinare lo stato di commit più recente.

 git add . && git checkout master -f 

Breve descrizione:

  • NON creerà alcun commit come fa git revert .
  • NON staccherà il tuo HEAD come git checkout .
  • Sostituirà tutte le modifiche locali e CANCELLERÀ tutti i file aggiunti dall’ultimo commit nel ramo.
  • Funziona solo con i nomi dei rami, quindi puoi ripristinare solo l’ultimo commit nel ramo in questo modo.

Ho trovato un modo molto più conveniente e semplice per ottenere i risultati sopra:

 git add . && git reset --hard HEAD 

dove HEAD punta all’ultima commit al tuo attuale ramo.

È lo stesso codice codice suggerito da boulder_ruby, ma ho aggiunto git add . prima di git reset --hard HEAD per cancellare tutti i nuovi file creati dall’ultimo commit poiché questo è ciò che la maggior parte delle persone si aspetta che io creda quando si ripristina l’ultimo commit.

Puoi farlo con i seguenti due comandi:

 git reset --hard [previous Commit SHA id here] git push origin [branch Name] -f 

Rimuoverà il tuo precedente commit Git.

Se vuoi mantenere le tue modifiche, puoi anche usare:

 git reset --soft [previous Commit SHA id here] 

Quindi salverà le tue modifiche.

Supponiamo che tu abbia il seguente commit in un file di testo chiamato ~/commits-to-revert.txt (ho usato git log --pretty=oneline per ottenerli)

 fe60adeba6436ed8f4cc5f5c0b20df7ac9d93219 0c27ecfdab3cbb08a448659aa61764ad80533a1b f85007f35a23a7f29fa14b3b47c8b2ef3803d542 e9ec660ba9c06317888f901e3a5ad833d4963283 6a80768d44ccc2107ce410c4e28c7147b382cd8f 9cf6c21f5adfac3732c76c1194bbe6a330fb83e3 fff2336bf8690fbfb2b4890a96549dc58bf548a5 1f7082f3f52880cb49bc37c40531fc478823b4f5 e9b317d36a9d1db88bd34831a32de327244df36a f6ea0e7208cf22fba17952fb162a01afb26de806 137a681351037a2204f088a8d8f0db6e1f9179ca 

Crea uno script di shell Bash per annullare ciascuno di essi:

 #!/bin/bash cd /path/to/working/copy for i in `cat ~/commits-to-revert.txt` do git revert $i --no-commit done 

Ciò ripristina tutto allo stato precedente, incluse le creazioni di file e directory e le eliminazioni, lo inoltra al ramo e si conserva la cronologia, ma viene ripristinata nella stessa struttura di file. Perché Git non ha un git revert --to è oltre me.

Alternative extra alle soluzioni di Jefromi

Le soluzioni di Jefromi sono sicuramente le migliori e dovresti sicuramente usarle. Tuttavia, per completezza, volevo anche mostrare queste altre soluzioni alternative che possono essere utilizzate anche per ripristinare un commit (nel senso che crei un nuovo commit che annulla le modifiche nel commit precedente , proprio come fa git revert ) .

Per essere chiari, queste alternative non sono il modo migliore per ripristinare i commit , le soluzioni di Jefromi lo sono , ma voglio solo sottolineare che puoi anche usare questi altri metodi per ottenere la stessa funzione di git revert .

Alternativa 1: Ripristini rigidi e morbidi

Questa è una versione leggermente modificata della soluzione di Charles Bailey per Revert to a commit di un hash SHA in Git? :

 # Reset the index to the desired commit git reset --hard  # Move the branch pointer back to the previous HEAD git reset --soft [email protected]{1} # Commit the changes git commit -m "Revert to " 

Questo funziona fondamentalmente usando il fatto che le reimpostazioni software lasceranno lo stato del commit precedente messo a punto nell’indice / area di staging, che è quindi ansible eseguire il commit.

Alternativa 2: Elimina l’albero corrente e sostituisci con quello nuovo

Questa soluzione proviene dalla soluzione di svick al vecchio commit di Checkout e ne fa un nuovo commit :

 git rm -r . git checkout  . git commit 

Analogamente al numero 1 alternativo, questo riproduce lo stato di nella copia di lavoro corrente. È necessario eseguire prima git rm perché git checkout non rimuoverà i file che sono stati aggiunti da .

Ecco un modo molto più semplice per tornare a un commit precedente (e averlo in uno stato non limitato, per fare ciò che vuoi):

 git reset HEAD~1 

Quindi, non c’è bisogno di ID di commit e così via 🙂

Supponendo che tu stia parlando di master e di quel rispettivo ramo (detto questo, questo potrebbe essere qualsiasi ramo di lavoro che ti interessa):

 # Revert local master branch to November 3rd commit ID git reset --hard 0d1d7fc32e5a947fbd92ee598033d85bfc445a50 # Revert remote master branch to November 3rd commit ID git push -f origin 0d1d7fc32e5a947fbd92ee598033d85bfc445a50:master 

Ho trovato la risposta da in post sul blog Elimina repo Git remoto su commit specifico .

OK, tornare al precedente commit in git è abbastanza facile …

Ritornare indietro senza mantenere le modifiche:

 git reset --hard  

Ritornare indietro mantenendo le modifiche:

 git reset --soft  

Spiega: utilizzando git reset, puoi ripristinare uno stato specifico, è comune utilizzarlo con un hash di commit come vedi sopra.

Ma come vedi la differenza sta usando i due flag --soft e --hard , per impostazione predefinita git reset usando --soft flag, ma è una buona pratica usare sempre il flag, spiego ogni flag:


–soft

Il flag predefinito come spiegato, non è necessario fornirlo, non modifica l’albero di lavoro, ma aggiunge tutti i file di modifiche pronti per il commit, quindi si torna allo stato di commit che non viene distriggersto.


–difficile

Fai attenzione a questo flag, resetta l’albero di lavoro e tutte le modifiche ai file tracciati e tutto sarà sparito!


Ho anche creato l’immagine qui sotto che può capitare in una vita reale lavorando con git:

git resettato su un commit

Niente qui ha funzionato per me oltre a questa combinazione esatta:

 git reset --hard  git push origin  --force 

La chiave qui è forzare la spinta, nessun commit aggiuntivo / messaggi di commit ecc.

Dopo tutte le modifiche, quando si preme tutti questi comandi, potrebbe essere necessario utilizzare:

 git push -f ... 

E non solo git push .

Esiste un comando (non una parte del nucleo di Git, ma è nel pacchetto git-extras ) specificamente per il ripristino e la stadiazione dei vecchi commit:

 git back 

Secondo la pagina man , può anche essere usato come tale:

 # Remove the latest three commits git back 3 

Seleziona il commit richiesto e controllalo

 git show HEAD git show HEAD~1 git show HEAD~2 

fino a ottenere il commit richiesto. Per fare in modo che la TESTA indichi ciò, fallo

 git reset --hard HEAD~1 

o git reset --hard HEAD~2 o qualsiasi altra cosa.

Ripristina il commit più recente e ignora tutte le modifiche locali:

 git reset --hard HEAD 

Credo che alcune persone possano venire a questa domanda volendo sapere come eseguire il rollback delle modifiche apportate che hanno apportato al loro master, cioè buttare via tutto e tornare all’origine / master, nel qual caso, fare questo:

 git reset --hard origin/master 

https://superuser.com/questions/273172/how-to-reset-master-to-origin-master

Per mantenere le modifiche dal commit precedente a HEAD e passare al commit precedente, fai:

 git reset  

Se le modifiche non sono richieste dal precedente commit a HEAD e semplicemente scartare tutte le modifiche, fare:

 git reset --hard  

Per pulire completamente la directory di un codificatore da alcune modifiche accidentali, abbiamo utilizzato:

 git add -A . git reset --hard HEAD 

Semplicemente git reset --hard HEAD si libererà delle modifiche, ma non si sbarazzerà dei “nuovi” file. Nel loro caso hanno trascinato accidentalmente una cartella importante da qualche parte in modo casuale, e tutti quei file sono stati trattati come nuovi da Git, quindi un reset --hard non l’ha risolto. Eseguendo il git add -A . in anticipo, li ha rintracciati esplicitamente tutti con git, per essere cancellati dal reset.

Questo è un altro modo per reimpostare direttamente su un commit recente

 git stash git stash clear 

Cancella direttamente tutte le modifiche che sono state apportate dall’ultimo commit.

PS: ha un piccolo problema; cancella anche tutte le modifiche di stash memorizzate di recente. Quale suppongo nella maggior parte dei casi non dovrebbe importare.

È ansible completare personalmente tutti questi passaggi iniziali e tornare a git repo.

  1. Estrai l’ultima versione del tuo repository da Bitbucket usando il comando git pull --all .

  2. Esegui il comando git log con -n 4 dal tuo terminale. Il numero dopo -n determina il numero di commit nel registro a partire dal commit più recente nella cronologia locale.

    $ git log -n 4

  3. Reimposta la cronologia della cronologia del tuo repository usando git reset --hard HEAD~N dove N è il numero di commit che vuoi recuperare. Nell’esempio seguente, la testa dovrebbe essere impostata su un commit, sull’ultimo commit nella cronologia del repository:

  4. Spingi la modifica a git repo usando git push --force per forzare la modifica.

Se vuoi git repository ad un commit precedente

 git pull --all git reset --hard HEAD~1 git push --force 

Revert è il comando per il rollback dei commit.

 git revert   

Campione:

git revert 2h3h23233

È in grado di prendere distanza dal TESTO come di seguito. Qui 1 dice “ripristina l’ultimo commit”.

git revert HEAD~1..HEAD

e poi fai git push

Se la situazione è urgente e vuoi solo fare ciò che l’interlocutore ha chiesto in modo rapido e sporco , supponendo che il tuo progetto sia nella directory “il mio progetto”:

  1. Copia l’intera directory e chiamala qualcos’altro, come “il mio progetto – copia”

  2. Fare:

     git reset --hard [first-4-letters&numbers-of-commit's-SHA] 

Quindi hai due versioni sul tuo sistema … puoi esaminare o copiare o modificare i file di interesse, o qualsiasi altra cosa, dal commit precedente. Puoi scartare completamente i file sotto “il mio progetto – copia”, se hai deciso che il nuovo lavoro non andava da nessuna parte …

The obvious thing if you want to carry on with the state of the project without actually discarding the work since this retrieved commit is to rename your directory again: Delete the project containing the retrieved commit (or give it a temporary name) and rename your “my project – copy” directory back to “my project”. Then probably do another commit fairly soon.

Git is a brilliant creation but you can’t just “pick it up on the fly”: also people who try to explain it far too often assume prior knowledge of other VCS [Version Control Systems] and delve far too deep far too soon, and commit other crimes, like using interchangeable terms for “checking out” – in ways which sometimes appear almost calculated to confuse a beginner.

To save yourself much stress you have to pretty much have to read a book on Git – I’d recommend “Version Control with Git” . And if you can trust me (or rather my scars) when I say “have to”, it follows that you might as well do it NOW . Much of the complexity of Git comes from branching and then remerging. But from your question there’s no reason why people should be blinding you with science .

Especially if, for example, this is a desperate situation and you’re a newbie with Git!

PS: One other thought: It is (now) actually quite simple to keep the Git repository (“repo”) in a directory other than the one with the working files. This would mean you would not have to copy the entire Git repository using the above quick & dirty solution. See the answer by Fryer using –separate-git-dir here . Be warned , though: If you have a “separate-directory” repository which you don’t copy, and you do a hard reset, all versions subsequent to the reset commit will be lost forever, unless you have, as you absolutely should, regularly backed up your repository, preferably to the cloud (eg Google Drive ) among other places.

As your commits are pushed remotely, you need to remove them. Let me assume your branch is develop and it is pushed over origin.

You first need to remove develop from origin:

 git push origin :develop (note the colon) 

Then you need to get develop to the status you want, let me assume the commit hash is EFGHIJK:

 git reset --hard EFGHIJK 

Lastly, push develop again:

 git push origin develop 

Try resetting to the desired commit –

git reset

(to check COMMIT_ID use git log )

This will reset all changed files to un-added state.

Now you can checkout all un-added files by

git checkout .

Check git log to verify your changes.

AGGIORNARE

If you have one and only commit in your repo, try

git update-ref -d HEAD

If you want to correct some error in the last commit a good alternative would be using git commit –amend command. If the last commit is not pointed by any reference, this will do the trick, as it create a commit with the same parent as the last commit. If there is no reference to the last commit, it will simply be discarded and this commit will be the last commit. This is a good way of correcting commits without reverting commits. However it has its own limitations.

Yet another simplest solution; you have to change branch to do this, but afterwards you can just run:

 git branch -f <> 0d1d7fc32e5a947fbd92ee598033d85bfc445a50 

For rollback (or to revert):

  1. git revert –no-commit “commit-code-to-remove” HEAD (eg git revert –no-commit d57a39d HEAD)
  2. git commit
  3. git push

Try above two steps, and if you find this is what you want then git push.

If you find something wrong do:

git revert –abort