Recuperar git de un crash

Mi server git queuepsó y ahora mis repos están en un estado inconsistente. RUnning git fsck --full muestra la siguiente salida.

error: refs/heads/data-8989 does not point to a valid object! dangling commit b8cfe9e3e58c64411795cf9676ff228b12607e95 dangling commit a817ef9d4a423b6efee62b9af16979e6433943b1 dangling commit 4f9d59b0dcfa34dd9592474fe487f568a20b07ea dangling commit 22af4033b6224d2b075db7138801fd7b8244eb37 missing commit d2b142ca7e165429a47b6e303fad349f3ae51cc7

¿Hay alguna forma de recuperar esto?

Los commits "colgantes" son normales incluso en un repository saludable: son la punta de un set de confirmaciones inalcanzables, y generalmente surgen de cosas como git rebase o git commit --amend (que deliberadamente abandona uno o más commits "antiguos" a favor) de la copy o copys "nuevas y mejoradas"). Sin embargo, en un repository defectuoso, algunos de estos commits colgantes -y otros commits alcanzables "detrás" de ellos- podrían ser los que pueda y desee recuperar.

El compromiso faltante es un problema más serio. Dado que solo se muestra uno de ellos, y exactamente una reference , la twig data-8989 no es válida, es probable que la confirmación faltante sea la que cometió la sugerencia de data-8989 . En este caso, uno (pero solo uno) de los compromisos pendientes puede ser un compromiso posterior en esa cadena.

Expresado visualmente, un gráfico normal podría verse más o less así:

  o--o--o <-- feature / \ ...--o--o--o------o--*--o <-- branch1 \ o--o-----------o <-- branch2 \ o----o--o <-- branch3 

donde cada o representa un compromiso. Cada confirmación "apunta hacia atrás" a su confirmación padre inmediata o, en el caso de la confirmación de fusión (marcada * ), apunta a dos padres, es decir, las dos confirmaciones que se fusionaron. Los nombres, la feature y branch1 y así sucesivamente, muestran cómo Git encuentra la punta de la twig. Una vez que Git tiene esta sugerencia de propina, Git usa las flechas internas hacia atrás para encontrar su (s) compromiso (s) primario (s), y luego usa los padres para encontrar las confirmaciones de abuelos, y así sucesivamente.

Ejecutar git fsck simplemente asegura que todos los commits en el repository puedan ser encontrados ( alcanzados ) de esta manera. Es normal que algunos no lo sean. Por ejemplo, podríamos decidir que branch3 es terrible y simplemente borrar la label, es decir, eliminar la twig. Los tres commits que solo son alcanzables desde branch3 ahora están abandonados. La propina está "colgando" y las otras dos, Git no se molesta en mencionarlas.

Tenga en count que una confirmación de punta de twig no tiene que ser el final de la cadena. Simplemente se trata como si fuera el último, cada vez que comienzas en ese consejo. Este es el caso de la feature , por ejemplo. Git no puede , al less no fácilmente, mirar hacia delante a lo largo de una cadena, porque todas las flechas internas de Git que conectan las confirmaciones van hacia atrás solamente , de niño a padre. (Esta es una parte importante de por qué git fsck es relativamente lento: tiene que trabajar mucho para, de hecho, invertir las flechas internas.) Es fácil comenzar desde la punta de la branch1 , trabajar hacia atrás, encontrar la fusión , trabaje hacia atrás y hacia arriba, y descubra que tiene la feature de confirmación de punta. Es difícil ir por el otro lado. Por lo tanto, Git normalmente funciona al revés.

Ahora, cuando un repository se daña , podemos perder las tags, o podemos perder algunos commits u otros objects internos (hay cuatro types de objects en total, pero nos concentraremos solo en los commits aquí). Los que tienen más probabilidades de dañarse son los creados más recientemente (para objects) o actualizados (para tags). Esto se debe a que, una vez creado, ningún object cambia alguna vez. 1 Los lockings informáticos tienden a perder o dañar los files recientemente tocados, en lugar de los files less activos less antiguos.

Considere lo que sucede si perdemos, no el nombre branch2 , pero su sugerencia se compromete:

  o--o--o <-- feature / \ ...--o--o--o------o--*--o <-- branch1 \ o--o ? <-- branch2 \ o----o--o <-- branch3 

En este caso, recibiremos una queja de que falta una confirmación, porque el nombre branch2 dice "find commit 1234567" o lo que sea, y no está allí . Es el que perdimos.

Sin embargo, no obtendremos ningún compromiso pendiente, porque la confirmación principal de branch2 también estaba en branch3 . Ahora esa confirmación solo está en branch3 , en lugar de estar en ambas twigs, porque la flecha hacia atrás saliente es parte de la confirmación que perdimos.

Si perdemos la punta de la branch1 , obtenemos una confirmación colgante:

  o--o--o <-- feature / \ ...--o--o--o------o--* ? <-- branch1 \ o--o-----------o <-- branch2 \ o----o--o <-- branch3 

La fusión * ya no tiene forma de encontrarse, por lo que está "colgando". Uno de sus padres se puede encontrar bajo la feature nombre, y el otro se puede encontrar si restauramos la fusión se compromete, pero si no lo hacemos, y dejamos que Git recoja las confirmaciones inalcanzables, el gráfico se networkinguce a esto :

  o--o--o <-- feature / ...--o--o--o ? <-- branch1 \ o--o-----------o <-- branch2 \ o----o--o <-- branch3 

Por lo tanto, dado un repository dañado, si no tiene copys de security u otros clones de los que recuperar elementos "faltantes", es conveniente dejar de modificarlo (no agregarle nada) y ejecutar git fsck --lost-found para hacer que Git guarde cualquier commit "colgado" en .git/lost-found/commit/ . A continuación, puede ver estos (utilizando git log by hash ID) para ver si son valiosos. Git también saveá blobs (files) inalcanzables en .git/lost-found/other/ ; puede ver los contenidos de los files directamente allí con cualquier visualizador de files y recuperar algunos files perdidos de esa manera.

Sin embargo, su mejor opción es tener otra clonación (o copys de security adecuadas).


1 Pero los objects se pueden embalar o volver a embalar , lo que afecta la forma en que se almacenan, por lo que esta no es una regla difícil.

De la documentation de git-fsck :

git-fsck testing SHA-1 y la cordura general del object, y hace un seguimiento completo de la accesibilidad resultante y todo lo demás. Imprime cualquier corrupción que encuentre (objects perdidos o malos), y si usa el indicador –unreachable también imprimirá objects que existen pero que no son accesibles desde ninguno de los nodos de cabeza especificados (o el set pnetworkingeterminado, como se ha mencionado más arriba).

Cualquier object corrupto que deba encontrar en copys de security u otros files (es decir, puede eliminarlos y realizar una synchronization con otro sitio con la esperanza de que alguien más tenga el object que ha dañado).

Necesita tener una copy de security o algún repository local clonado.