Examinar confirmaciones huérfanas en Git

102

Mi repositorio de git de alguna manera se ha vuelto inestable: cargué msysgit esta mañana y en lugar de que el nombre de la rama se muestre después del directorio actual, dice "((ref: re ...))", 'git status' informa todo como un nuevo archivo, 'git log' y 'git reflog' me dicen "fatal: mala revisión predeterminada 'HEAD'", y así sucesivamente.

Hacer 'git reflog --all' o 'gitk --all' me muestra que el resto del repositorio está intacto, pero parece que la rama en la que estaba trabajando acaba de desaparecer, lo que explica por qué HEAD no parece existir / señalar cualquier cosa.

Sé que git mantiene todo tipo de información, y supongo que mis confirmaciones se han quedado huérfanas de alguna manera, así que ¿hay algún comando que me muestre esas confirmaciones para que pueda restablecer HEAD en ellas?

EDITAR: Oh cielos. Descubrí 'git fsck' y 'git fsck --full' informa "fatal: object 03ca4 ... is corrupted". ¿Qué diablos puedo hacer al respecto?

EDITAR: Oh, Dios mío, Dios mío. Revisé otra rama, luego intenté volver a crear la rama original con el mismo nombre usando 'git checkout -b lostbranchname', y git dice "error: no se pueden resolver las referencias de referencia / heads / lostbranchname: Sin error, fatal: Failed para bloquear ref para actualización: No hay error ". 'Sin error' debe ser un error particularmente desagradable. Entonces parece que todavía está dando vueltas, pero no se puede usar y no se puede matar.

EDITAR: Super duper oh cielos. He desempacado, reempacado y reemplazado cosas como se sugiere aquí: ¿Cómo recuperar objetos Git dañados por fallas en el disco duro? , pero ahora recibo otro hash informado como corrupto, por algo tan inocuo como 'git status'. Creo que todo está regado. Git es encantador y todo eso, pero no debería tener que lidiar con este tipo de cosas.

Ben Hymers
fuente
En cuanto a git checkout -b lostbranchname: si solo le importa el nombre de la rama (no el contenido de la misma), puede eliminarla manualmente (o cambiarle el nombre) .git/refs/heads/lostbranchname, es de esperar que funcione.
Antony Hatchkins
1
¿Y no tiene un flujo ascendente donde empuje esta carpeta git?
Lakshman Prasad
1
Lamentablemente no, en realidad es una especie de repositorio sustituto para un sistema de control de fuente inferior, solo lo estoy usando localmente para obtener todas las características y sutilezas de git sin la molestia del otro sistema. Pero al menos el otro sistema no se corrompe al azar. Aún así, eso significa que todo lo que he perdido son mis cambios desde la última vez que me registré en el otro sistema, que ya he recuperado. ¡Es hora de comenzar un repositorio nuevo!
Ben Hymers
7
Dudaría en decir que git te hizo "lidiar con este tipo de cosas" o que se corrompió. Nada más que una copia de seguridad puede ser completamente estable frente a la pérdida de datos.
Cascabel
1
Lo sé de verdad, estoy (naturalmente) un poco molesto por haber perdido mi bonita historia. No es culpa de git, cualquier otro sistema se comportaría igual dados los errores del sistema de archivos.
Ben Hymers

Respuestas:

134

En lugar de dejar esto abierto, creo que daré una respuesta a mi propia pregunta. Usar git reflog --alles una buena manera de buscar confirmaciones huérfanas, y usar los hashes SHA1 de eso puede reconstruir el historial.

En mi caso, sin embargo, el repositorio estaba dañado, así que esto no ayudó; git fsckpuede ayudarlo a encontrar y, a veces, corregir errores en el repositorio.

Ben Hymers
fuente
3
Gracias. Este es el único lugar donde encontré esta información al intentar extraer una solicitud de extracción huérfana en github. Resolvió mi problema.
SystemParadox
6
en caso de que alguien quiera todo en gitk: [alias] orphank = !gitk --all --date-order ``git reflog | cut -c1-7``&(editar: imagina esas comillas dobles donde las simples; el escape no parece funcionar aquí)
mbx
1
Increíble consejo @mbx! ¡Muy útil para poder ver gráficamente los vínculos entre confirmaciones huérfanas!
Ben Hymers
@BenHymers Sería genial, si pudiéramos obtener líneas de puntos para las relaciones de compromiso como "rebase / squash" también. Todavía no he encontrado la manera de hacerlo.
mbx
No sabía sobre reflog cuando escribí la respuesta anterior. ¡Es una herramienta tan útil!
Jamey Hicks
17

Con git 2.9.x / 2.10 (Q3 2016), no tendrás que usar git reflog --allmás, git reflogserá suficiente.

Véase el compromiso 71abeb7 (3 de junio de 2016) de SZEDER Gábor ( szeder) .
(Combinado por Junio ​​C Hamano - gitster- en el compromiso 7949837 , 06 de julio de 2016)

reflog: continúa recorriendo los reflogúltimos compromisos de root

Si un repositorio contiene más de una confirmación raíz, entonces su reflog HEAD puede contener múltiples "eventos de creación", es decir, entradas cuyo valor "from" es el nulo sha1.
El listado de un reflog de este tipo actualmente se detiene prematuramente en la primera entrada de este tipo, incluso cuando el reflog aún contiene entradas más antiguas.
Esto puede asustar a los usuarios haciéndoles pensar que su reflog se truncó después ' git checkout --orphan'.

Continúe recorriendo el reflog más allá de dichos eventos de creación según el valor "nuevo" de la entrada del reflog anterior.

VonC
fuente
4

Una buena característica de git es que detecta corrupción. Sin embargo, no incluye corrección de errores para protegerse de la corrupción.

Espero que haya enviado el contenido de este repositorio a otra máquina o que tenga copias de seguridad para recuperar las partes dañadas.

No tengo ninguna experiencia con git en Windows, pero nunca he visto este tipo de comportamiento con git en Linux o OS X.

Jamey Hicks
fuente
3

Normalmente encuentro el git reflogresultado confuso. Es mucho más fácil para mí entender un gráfico de confirmación de git log --graph --reflog. Anular el formato para mostrar solo resúmenes de confirmación también puede hacer que el gráfico sea más fácil de seguir:

$ git alias graph "log --graph --all --format='%h %s%n        (%an, %ar)%d' --abbrev-commit
$ git graph --reflog

* f06abeb Add feature
|         (Sue Dakota, 4 days ago) (HEAD -> master)
* f126291 Fix the build
|         (Oski M. Wizard, 5 days ago) (origin/master, master)
* 3c4fb9c Break the build
|         (Alyssa P. Hacker, 5 days ago)
| * e3124bf fixup! More work for feature
| |         (Sue Dakota, 4 days ago)
| | * 6a7a52e Lost commit
| |/          (Sue Dakota, 4 days ago)
| * 69d9438 More work for feature
| |         (Sue Dakota, 2 weeks ago)
| * 8f69aba Initial work for feature
|/          (Sue Dakota, 3 weeks ago)
* d824fa9 Fix warnings from the linter
|         (Theo Ristudent, 4 weeks ago)
* 9f782b8 Fix tests flakes
|         (Tess Driven, 5 weeks ago)

A partir de eso, está claro que e3124bfy 6a7a52eson huérfanos sin referencia, y hay contexto de las confirmaciones de sus ancestros.

jamesdlin
fuente
¡Me ahorró horas de trabajo perdido ahora mismo! borró accidentalmente una rama local que tenía confirmaciones no presionadas, git reflog --allno las muestra, git log --graph --reflogy eran muy visibles ...
Adam.Er8