Buscar y restaurar un archivo eliminado en un repositorio Git


Digamos que estoy en un repositorio Git. Borro un archivo y confirmo ese cambio. Sigo trabajando y hago más commits. Luego, encuentro que necesito restaurar ese archivo.

Sé que puedo revisar un archivo usando git checkout HEAD^ foo.bar, pero realmente no sé cuándo se eliminó ese archivo.

  1. ¿Cuál sería la forma más rápida de encontrar la confirmación que elimina un nombre de archivo dado?
  2. ¿Cuál sería la forma más fácil de recuperar ese archivo en mi copia de trabajo?

Espero no tener que hacerlo examinar manualmente mis registros, checkout todo el proyecto para un SHA dado y luego copiar manualmente ese archivo en mi checkout proyecto original.

Author: 7ochem, 2009-06-05

19 answers

Encuentra la última confirmación que afectó la ruta dada. Como el archivo no está en el commit HEAD, este commit debe haberlo eliminado.

git rev-list -n 1 HEAD -- <file_path>

Luego revisa la versión en el commit anterior, usando el símbolo de caret (^):

git checkout <deleting_commit>^ -- <file_path>

O en un comando, si $file es el archivo en cuestión.

git checkout $(git rev-list -n 1 HEAD -- "$file")^ -- "$file"

Si está utilizando zsh y tiene activada la opción EXTENDED_GLOB, el símbolo de la casilla no funcionará. Puede usar ~1 en su lugar.

git checkout $(git rev-list -n 1 HEAD -- "$file")~1 -- "$file"
 2768
Author: CB Bailey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-03 17:11:57
  1. Use git log --diff-filter=D --summary para obtener todas las confirmaciones que han eliminado archivos y los archivos eliminados;
  2. Utilice git checkout $commit~1 filename para restaurar el archivo eliminado.

Donde $commit es el valor de la confirmación que has encontrado en el paso 1, por ejemplo, e4cf499627

 736
Author: Robert Munteanu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-23 14:58:03

Para restaurar todos los archivos eliminados en una carpeta, ingrese el siguiente comando.

git ls-files -d | xargs git checkout --
 306
Author: Manu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-20 21:49:17

Llegué a esta pregunta buscando restaurar un archivo que acabo de eliminar pero aún no había confirmado el cambio. En caso de que se encuentre en esta situación, todo lo que necesita hacer es lo siguiente:

git checkout HEAD -- path/to/file.ext

 105
Author: Brett,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-10 00:03:18

Si estás loco, usa git-bisect. Esto es lo que debe hacer:

git bisect start
git bisect bad
git bisect good <some commit where you know the file existed>

Ahora es el momento de ejecutar la prueba automatizada. El comando shell '[ -e foo.bar ]' devolverá 0 si existe foo.bar, y 1 en caso contrario. El comando" run " de git-bisect usará la búsqueda binaria para encontrar automáticamente la primera confirmación donde falla la prueba. Comienza a la mitad del rango dado (de bueno a malo) y lo corta a la mitad según el resultado de la prueba especificada.

git bisect run '[ -e foo.bar ]'

Ahora estás en el commit que lo borró. Desde aquí, puede volver al futuro y utilizar git-revert para deshacer el cambio,

git bisect reset
git revert <the offending commit>

O puedes volver atrás un commit e inspeccionar manualmente el daño:

git checkout HEAD^
cp foo.bar /tmp
git bisect reset
cp /tmp/foo.bar .
 84
Author: Josh Lee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-28 19:10:53

Mi nuevo alias favorito, basado en bonyiii 's answer (upvoted), y mi propia respuesta acerca de" Pasar un argumento a un comando Git alias":

git config alias.restore '!f() { git checkout $(git rev-list -n 1 HEAD -- $1)~1 -- $(git diff --name-status $(git rev-list -n 1 HEAD -- $1)~1 | grep '^D' | cut -f 2); }; f'

He perdido un archivo, eliminado por error hace unos pocos commits?
Rápido:

git restore my_deleted_file

Crisis evitada.


Robert Dailey propone en los comentarios el siguiente alias:

restore-file = !git checkout $(git rev-list -n 1 HEAD -- "$1")^ -- "$1"

Y jegan agrega en los comentarios:

Para establecer el alias de la línea de comandos, usé este comando:

git config --global alias.restore "\!git checkout \$(git rev-list -n 1 HEAD -- \"\$1\")^ -- \"\$1\"" 
 63
Author: VonC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-10 06:03:55

Si conoce el nombre del archivo, esta es una manera fácil con los comandos básicos:

Lista todas las confirmaciones para ese archivo.

git log -- path/to/file

La última confirmación (la más alta) es la que borró el archivo. Así que necesitas restaurar la penúltima confirmación.

git checkout {second to last commit} -- path/to/file
 43
Author: wisbucky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-15 11:48:31

Para restaurar un archivo eliminado y comprometido:

git reset HEAD some/path
git checkout -- some/path

Fue probado en la versión 1.7.5.4 de Git.

 28
Author: Fedir RYKHTIK,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-14 20:26:38

Si solo realizaste cambios y borraste un archivo, pero no lo confirmaste, y ahora rompiste con tus cambios

git checkout -- .

Pero sus archivos eliminados no regresaron, simplemente haga el siguiente comando:

git checkout <file_path>

Y listo, su archivo está de vuelta.

 22
Author: Paulo Linhares - Packapps,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-02 15:30:19

Tengo esta solución.

  1. Obtenga el id de la confirmación donde se eliminó el archivo utilizando una de las siguientes formas.

    • git log --grep=*word*
    • git log -Sword
    • git log | grep --context=5 *word*
    • git log --stat | grep --context=5 *word* # recomendado si apenas recuerda cualquier cosa
  2. Usted debe conseguir algo como:

Commit bfe68bd117e1091c96d2976c99b3bcc8310bebe7 Autor: Alexander Orlov Fecha: Jue May 12 23: 44:27 2011 +0200

replaced deprecated GWT class
- gwtI18nKeySync.sh, an outdated (?, replaced by a Maven goal) I18n generation script

Commit 3ea4e3af253ac6fd1691ff6bb89c964f54802302 Autor: Alexander Orlov Fecha: Jue May 12 22: 10:22 2011 +0200

3. Ahora usando el id de confirmación bfe68bd117e1091c96d2976c99b3bcc8310bebe7 do:

git checkout bfe68bd117e1091c96d2976c99b3bcc8310bebe7^1 yourDeletedFile.java

Como el commit id hace referencia al commit donde el archivo ya fue borrado, necesita hacer referencia al commit justo antes de bfe68b, lo que puede hacer añadiendo ^1. Esto significa: dame la confirmación justo antes de bfe68b.

 21
Author: Alex,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-25 18:07:17
git checkout /path/to/deleted.file
 14
Author: user1528493,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-25 18:05:51

En muchos casos, puede ser útil usar coreutils (grep, sed, etc.) junto con Git. Ya conozco estas herramientas bastante bien, pero Git no tanto. Si quisiera hacer una búsqueda de un archivo eliminado, haría lo siguiente:

git log --raw | grep -B 30 $'D\t.*deleted_file.c'

Cuando encuentre la revisión / confirmación:

git checkout <rev>^ -- path/to/refound/deleted_file.c

Al igual que otros han declarado antes que yo.

El archivo ahora será restaurado al estado que tenía antes de la eliminación. Recuerde volver a comprometerlo en el árbol de trabajo si desea mantenerlo alrededor.

 10
Author: Thomas E,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-14 20:27:59

git undelete path/to/file.ext

  1. Pon esto en tu .bash_profile (u otro archivo relevante que se cargue cuando abres una consola de comandos):

    git config --global alias.undelete '!sh -c "git checkout $(git rev-list -n 1 HEAD -- $1)^ -- $1" -'
    
  2. Luego use:

    git undelete path/to/file.ext
    

Este alias comprueba primero el último commit donde existió este archivo, luego hace un checkout de git de la ruta del archivo desde el último commit donde existió este archivo. fuente

 9
Author: Beau Smith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-08 01:13:40

Así que tuve que restaurar un montón de archivos eliminados de un commit específico y lo manejé con dos comandos:

git show <rev> --diff-filter=D --summary --name-only --no-commit-id | xargs git checkout <rev>^ -- 
git show <rev> --diff-filter=D --summary --name-only --no-commit-id | xargs git reset HEAD 

(Observe el espacio final al final de cada comando.)

Los archivos se habían añadido a la .gitignore archivo y luego se borra con git rm, necesitaba restaurar los archivos, pero luego unstage ellos. Tenía cientos de archivos para restaurar, escribir cosas manualmente para cada archivo como en los otros ejemplos iba a ser demasiado lento.

 6
Author: kzar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-15 11:49:46
user@bsd:~/work/git$ rm slides.tex
user@bsd:~/work/git$ git pull 
Already up-to-date.
user@bsd:~/work/git$ ls slides.tex
ls: slides.tex: No such file or directory

Restaurar el archivo eliminado:

user@bsd:~/work/git$ git checkout
D       .slides.tex.swp
D       slides.tex
user@bsd:~/work/git$ git checkout slides.tex 
user@bsd:~/work/git$ ls slides.tex
slides.tex
 4
Author: user1797498,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-29 16:35:45

Yo tenía la misma pregunta. Sin saberlo, había creado un compromiso colgando.

Lista confirmaciones colgantes

git fsck --lost-found

Inspeccione cada confirmación colgando

git reset --hard <commit id>

Mis archivos reaparecieron cuando me moví a la confirmación colgando.

git status por la razón:

“HEAD detached from <commit id where it detached>”

 4
Author: rustyMagnet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-04 17:08:40

En nuestro caso eliminamos accidentalmente archivos en un commit y algunos commit más tarde nos dimos cuenta de nuestro error y queríamos recuperar todos los archivos que se eliminaron, pero no los que se modificaron.

Basado en la excelente respuesta de Charles Bailey aquí está mi frase:

git co $(git rev-list -n 1 HEAD -- <file_path>)~1 -- $(git diff --name-status $(git rev-list -n 1 HEAD -- <file_path>)~1 head | grep '^D' | cut -f 2)
 3
Author: bonyiii,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-02 20:52:39

Si conoce la confirmación que eliminó el archivo(s), ejecute este comando donde <SHA1_deletion> es la confirmación que eliminó el archivo:

git diff --diff-filter=D --name-only <SHA1_deletion>~1 <SHA1_deletion> | xargs git checkout <SHA1_deletion>~1 --

La parte anterior a la tubería enumera todos los archivos que se eliminaron en el commit; todos son checkout desde el commit anterior para restaurarlos.

 3
Author: Tony Wickham,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-08 19:27:52
$ git log --diff-filter=D --summary  | grep "delete" | sort
 -1
Author: kujiy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-05 01:01:30