2012-05-28 12 views
9

Agregué algunos archivos al índice pero luego, por error, los borré con git reset --hard. ¿Cómo los recupero? Esto es lo que sucedió:Recuperar archivos que se agregaron al índice pero luego se eliminaron mediante un reinicio de git

  1. he añadido todos los archivos usando git add .
  2. entonces cometí
  3. Al revisar el estado, aún había archivos que no fueron incluidos en la confirmación desde el complemento, lo que era extraña
  4. añadí los archivos sin seguimiento de nuevo y funcionó esta vez
  5. Pero yo quería que todo fuera en 1 única confirmación así que busqué la forma de unstage lo que acabo comprometido
  6. utilicé git reset --hard HEAD^ - mala idea, obviamente, todos los archivos fueron borrados
  7. así, entonces yo solía git reflog para encontrar donde lo dejé
  8. Luego utiliza git reflog ______ a volver a mi última confirmación.
  9. luego usé git reset HEAD para borrar la confirmación (lo que debería haber hecho originalmente) pero los archivos que agregué (ver más arriba) después de la confirmación aún se habían ido.

¿Cómo recupero esos archivos?

+0

Si nunca se cometieron, y que ha restablecer el índice de distancia, probablemente no puedas. – Ashe

+0

¿Hay alguna manera de deshacer el restablecimiento del índice? –

+1

Puede tener suerte ejecutando 'git fsck --full' y un poco de paciencia mientras tamiza a través de todos los blobs inalcanzables que va a informar. – knittl

Respuesta

20

Primero, haga una copia de seguridad completa de su repositorio de Git!

Cuando git add un archivo, git creará un blob del contenido de este archivo y lo agregará a su base de datos de objetos (.git/objects/??/*). mirada

Vamos a sus comandos, uno por uno:

he añadido todos los archivos usando git add.

$ git add . 

Esto agregará todos los archivos contenidos en el directorio actual y sus subdirectorios a la base de datos de objetos de Git. Los archivos sin seguimiento que coincidan con los patrones de los archivos .gitignore no se agregarán. Los archivos de árbol también se escribirán. Por favor, mira el final de mi respuesta.

entonces comprometido

$ git commit -m'added all files' 

Esto va a escribir un nuevo objeto comprometer a la base de datos de objetos. Este compromiso hará referencia a un solo árbol. El árbol hace referencia a blobs (archivos) y otros árboles (subdirectorios).

Al revisar el estado, todavía hay archivos que no fueron incluidos en la confirmación desde el complemento, lo que era extraño

$ git status 

puedo pensar en dos escenarios en que sucede esto: algo modificó sus archivos o se agregaron nuevos archivos a sus espaldas.

que añaden los archivos sin seguimiento de nuevo y funcionó esta vez

$ git add . 

Asumo que utilizó el mismo comando add de nuevo, como en el paso 1.

pero quería que todo sea en 1 única confirmación así que busqué la forma de unstage lo que acabo comprometido

te diré una mejor manera al final de esta respuesta, que no requiere el usuario para emitir una potencialmente peligrosa reset

usé Git restablecer --hard CABEZA^- mala idea, obviamente, todos los archivos se suprimieron

$ git reset --hard HEAD^ 

Este comando fijará su árbol de trabajo actual y el índice que se va exactamente en la confirmación HEAD^ (la penúltima comprometerse). En otras palabras, descartará cualquier cambio local no confirmado y moverá el puntero de bifurcación hacia atrás una confirmación. No toca archivos sin seguimiento.

tan Luego utiliza reflog git para encontrar donde lo dejé

$ git reflog 

Esto muestra las últimas confirmaciones que fueron recientemente desprotegidos (idénticos a git reflog HEAD). Si especifica un nombre de rama, le mostrará los últimos commits a los que esta rama señaló recientemente.

Luego utiliza git reflog __ a volver a mi última confirmación.

No estoy seguro sobre éste. git reflog es (principalmente) un comando de solo lectura y no se puede usar para "volver" a commits. Solo puede usarlo, para encontrar commits apuntado a una rama (o HEAD).

Luego utiliza reset HEAD git a unstage el commit (lo que debería haber hecho en un principio), pero los archivos que añade (véase más arriba) después de la confirmación se ha ido todavía. $ git reset CABEZA

Esto no unstage este cometido, pero será por etapas unstage todo (pero no confirmada) cambios del índice. Originalmente (primera etapa), que quería decir git reset HEAD^ (o git reset --mixed HEAD^) - Esto dejará su árbol de trabajo sin tocar, pero establece el índice para que coincida con el árbol a la que apunta la confirmación nombrado por HEAD^.


Ahora, para recuperar sus archivos, usted tiene que utilizar git fsck --full --unreachable --no-reflog. Escaneará todos los objetos en la base de datos de objetos de Git y realizará un análisis de accesibilidad. Desea buscar objetos blob.También debe haber un objeto tree, que describe el estado después de su segunda git add .

git cat-file -p <object hash> imprimirá el contenido de los archivos, por lo que puede comprobar que tiene los objetos adecuados. Para blobs, puede usar la redirección de IO para escribir el contenido en el nombre de archivo correcto. Para los árboles, debes usar los comandos de git (git read-tree). Si solo se trata de unos pocos archivos, es mejor que los escriba directamente en los archivos.


algunas notas aquí:

Si desea añadir archivos a la última confirmación (o editar su mensaje de entrega), sólo pueden utilizar git commit --amend. Básicamente es un contenedor alrededor del git reset --soft HEAD^ && git commit -c [email protected]{1}.

Además, casi nunca es una buena idea usar git add .. Por lo general, solo desea usarlo la primera vez, cuando está creando un nuevo repositorio. Las mejores alternativas son git add -u, git commit -a, que representarán todos los cambios en los archivos rastreados. Para rastrear nuevos archivos, mejor especifíquelos explícitamente.

+0

Muchas gracias. Voy a intentar esto ahora. –

+0

¡SÍ! Cada blob tenía el código faltante. Debes alojar tu propio blog de Git. Gracias por tomarse el tiempo para ayudarme, muy apreciado. –

+1

Ahorrador de vida ... muchas gracias: D – c0deNinja

14

Tuve un problema similar pero tenía muchos blobs y árboles colgantes en mi repositorio, así que terminé filtrando con grep la salida de todos los blobs colgantes e imprimí los que coincidían. Suponiendo ${UNIQUE_CODE} es un código que es único para los archivos que tenía en el índice, entonces esto debe darle los hashes de las manchas que usted está buscando:

for b in $(git fsck --lost-found | grep blob | awk '{print $3}'); do git cat-file -p $b | grep -q ${UNIQUE_CODE} && echo $b; done 
+0

Gracias hombre, me salvó el día! Sin embargo, para recuperar, hice lo siguiente: para b en $ (git fsck --lost-found | grep blob | awk '{print $ 3}'); do git cat-file -p $ b> ../$b; hecho –

Cuestiones relacionadas