Ripristina le modifiche dopo il checkout accidentale?

Quello che segue era lo stato del mio repository.

[~/rails_apps/jekyll_apps/nepalonrails (design)⚡] ➔ gst # On branch design # Changed but not updated: # (use "git add/rm ..." to update what will be committed) # (use "git checkout -- ..." to discard changes in working directory) # # modified: _layouts/default.html # deleted: _site/blog/2010/04/07/welcome-to-niraj-blog/index.html # deleted: _site/blog/2010/04/08/the-code-syntax-highlight/index.html # deleted: _site/blog/2010/05/01/showing-demo-to-kalyan/index.html # deleted: _site/config.ru # deleted: _site/index.html # deleted: _site/static/css/style.css # deleted: _site/static/css/syntax.css # modified: static/css/style.css # no changes added to commit (use "git add" and/or "git commit -a") 

Accusato, ho fatto il git checkout -f e ora i cambiamenti sono andati che non avrei dovuto fare.

 [~/rails_apps/jekyll_apps/nepalonrails (design)⚡] ➔ git co -f [~/rails_apps/jekyll_apps/nepalonrails (design)] ➔ gst # On branch design nothing to commit (working directory clean) [~/rails_apps/jekyll_apps/nepalonrails (design)] ➔ 

Posso tornare indietro le modifiche?

Non penso che tu possa recuperare quei dati privati ​​(“privato” come in “non aggiunto all’indice, né impegnato”, quindi sconosciuto a git), a meno che tu non abbia altro processo di backup in atto per la tua attuale directory di lavoro.

Anche se questo non è proposto nella pagina Git Alias , vorrei discutere di qualche alias per il checkout (come c’è l’ alias rm /bin/rm -i usage):

 [alias] co = !sh -c 'git stash; git stash apply; git checkout "$*"' 

con il ‘ git stash; git stash apply git stash; git stash apply ‘essere la “tecnica del checkpoint” usata da Brian Campbell nella sua risposta .

Questo problema mi ricorda un dibattito su questo comportamento su ycombinator (estratti):


Ho perso molti dati con git.
La maggior parte ha a che fare con comandi dal suono innocuo che non richiedono conferma quando si eliminano i dati .
Ad esempio, git checkout filename è equivalente a svn revert filename .
Ovviamente git checkout branchname fa qualcosa di completamente diverso.
Se un ramo e un file condividono lo stesso nome, git passerà automaticamente al cambio dei rami, ma ciò non impedirà il completamento automatico del bash di rovinare la giornata.

Ecco un’idea pazzesca: se hai un’azione innocua e un’azione pericolosa, non etichettali con lo stesso comando.


Fastidioso, forse, ma questo è un errore dell’utente, non un errore di progettazione. Con git, se voglio eliminare senza perdite la mia copia di lavoro, posso semplicemente ” git stash “.
Secondo la tua logica, “rm” è difettoso perché non chiede conferma quando passi -f invece di -i . Bene sì. Scusate.


La tua analogia sarebbe più accurata se rm somename fosse l’equivalente di apt-get update , e rm othername era rm -fr othername .
Tuttavia, non può essere giusto che ” get checkout foo ” faccia una delle due cose COMPLETAMENTE diverse a seconda che ci sia o meno un file chiamato foo nella directory corrente


Ecco un’altra pazza idea: non eseguire ‘ git checkout ... ‘ su un albero di lavoro sporco. Problema risolto.
Un altro: non riutilizzare nomi di file come nomi di diramazioni.
Ad essere onesti: ho lo stesso problema con invocazioni incuranti di ” rm ” che rovinano la mia giornata, ma quando mormoro maledizioni è nella mia pigrizia / stupidità e non nei bash completamenti o nel comportamento di ” rm

Un’altra cosa che puoi guardare è attraverso il tuo IDE. Accidentalmente ho controllato 2 file e sono stato in grado di riportare le modifiche attraverso la “cronologia locale” del mio IDE (netbeans). Che Benedizione!

A meno che tu non abbia mai usato git add o git stash con quei file in precedenza, sfortunatamente no. Se li hai aggiunti o nascosti, dovresti riuscire a trovare i loro hash attraverso il git reflog .

Non sono mai stato a mio agio con questo comportamento distruttivo del git checkout . Forse un utile miglioramento sarebbe avere questo tipo di git checkout crea automaticamente una scorta (in modo che i file vengano catturati attraverso il reflog) prima di sovrascrivere il tuo lavoro.

Quanto segue può essere applicato nel caso in cui si utilizzi vim su Linux.

  • Se i file sono aperti in un buffer attivo, hai il contenuto del file finché non ricarichi il file in vim e puoi ripristinarlo salvandolo. .

  • Se i file non sono aperti in un buffer attivo, ma sono sporchi, dovrebbe esserci un file .swp nella directory di origine che ha anche una copia del contenuto che è recuperabile tramite vim -r file.swp .

  • Se i file non sono né aperti nel buffer attivo né sporchi e se la tua copia di lavoro si trova su una partizione ext3 o ext4, allora extundelete potrebbe essere in grado di trovare i file .swp eliminati di recente e / o una versione precedente dei file di origine. Rimontare la partizione in sola lettura, ad esempio mount -o remount,ro /mnt/point ed eseguire

     extundelete --recover-directory /path/to/working/copy /dev/sdaX 

    Se la partizione che contiene la copia di lavoro è la partizione di root, potrebbe rifiutarsi di rimontare, quindi provare ad uccidere tutti i servizi e, se non ci sono ancora, spegnere e avviare usando un Live CD / USB / PXE, come GRML , ed eseguire il sopra. Ho avuto successo nel recuperare uno dei tre file persi in questo modo.

se usi Eclipse come IDE ed EGit , hai nel tuo file il menu Team:

  1. fai clic con il tasto destro sul tuo file dall’interno
  2. Lista “Team” -> “Mostra cronologia locale”

vedrai tutte le versioni salvate localmente senza alcun nome di salvataggio, nel mio caso però, puoi facilmente controllare tutte le modifiche non tracciate dalle funzionalità di git e ripristinare il codice mancante.

Non c’è nulla che tu possa fare con i comandi git, ma se stai usando IDE puoi recuperare le tue modifiche. Sto usando PhpStorm dove possiamo vedere la storia delle modifiche ai file. Basta fare clic destro sul file e fare clic su mostra la cronologia locale. Nella scheda Modifiche esterne, puoi trovare le modifiche locali che hai rimosso accidentalmente.