Listado y eliminación de confirmaciones de Git que no están bajo ninguna twig (¿colgando?)

Tengo un repository de Git con muchos compromisos que no están bajo ninguna twig en particular, puedo git show , pero cuando trato de enumerar las twigs que los contienen, no informa nada.

Pensé que este es el problema de los commit / tree colgando (como resultado de la twig -D), así que borré el repository, pero todavía veo el mismo comportamiento después de eso:

 $ git fetch origin $ git fsck --unreachable $ git fsck 

Sin salida, nada colgando (¿verdad?). Pero el compromiso existe

 $ git show 793db7f272ba4bbdd1e32f14410a52a412667042 commit 793db7f272ba4bbdd1e32f14410a52a412667042 Author: ... 

y no es alcanzable a través de ninguna twig como

 $ git branch --contains 793db7f272ba4bbdd1e32f14410a52a412667042 

no da salida

¿Cuál es exactamente el estado de ese compromiso? ¿Cómo puedo hacer una list de todas las confirmaciones en un estado similar? ¿Cómo puedo eliminar commits como esos?

Sin salida, nada colgando (¿verdad?)

Tenga en count que las confirmaciones a las que se hace reference desde su reflog se consideran alcanzables.

¿Cuál es exactamente el estado de ese compromiso? ¿Cómo puedo hacer una list de todas las confirmaciones con estado similar?

Pase --no-reflogs para convencer a git fsck que se los muestre.

¿Cómo puedo eliminar commits como esos?

Una vez que expiren sus inputs de reflog, esos objects también serán limpiados por git gc .

La caducidad está regulada por las gc.pruneexpire , gc.reflogexpire y gc.reflogexpireunreachable . Cf. git help config .

Los valores pnetworkingeterminados son todos bastante razonables.

Para eliminar todas las confirmaciones pendientes y aquellas a las que se puede acceder desde los reflogs, haga lo siguiente:

 git reflog expire --expire-unreachable=now --all git gc --prune=now 

Pero asegúrese de que esto es lo que quiere. Te recomiendo que leas las páginas man, pero esta es la esencia:

git gc elimina objects inalcanzables (commits, trees, blobs (files)). Un object es inalcanzable si no es parte del historial de alguna twig. En realidad es un poco más complicado:

git gc hace algunas otras cosas pero no son relevantes aquí y no son peligrosas.

Los objects inalcanzables que tienen less de dos semanas no se eliminan, por lo que usamos --prune=now que significa "eliminar objects inalcanzables que se crearon antes".

Los objects también pueden ser alcanzados a través del reflog. Mientras que las sucursales registran la historia de algún proyecto, los reflogs registran el historial de estas twigs. Si modificas, restableces, etc., las confirmaciones se eliminan del historial de la sucursal, pero git las conserva en caso de que te des count de que cometiste un error. Los Reflogs son una forma conveniente de descubrir qué operaciones destructivas (y otras) se realizaron en una twig (o HEAD), lo que facilita deshacer una operación destructiva.

Por lo tanto, también debemos eliminar los reflogs para eliminar todo lo que no se puede acceder desde una sucursal. Lo hacemos al caducar –todos los reflogs. De nuevo, git guarda un poco de los reflogs para proteger a los usuarios, así que de nuevo tenemos que decirle que no lo haga: --expire-unreachable=now .

Como utilizo principalmente el reflog para recuperarme de las operaciones destructivas, generalmente uso --expire=now lugar, lo que elimina por completo los reflogs.

 git branch --contains 793db7f272ba4bbdd1e32f14410a52a412667042 

Probablemente solo necesite ser

 git branch -a --contains 793db7f272ba4bbdd1e32f14410a52a412667042 

para informar también sobre las sucursales de los controles remotos

Tuve el mismo problema, aún después de seguir todos los consejos en este hilo:

 git reflog expire --expire-unreachable=now --all git gc --prune=now git fsck --unreachable --no-reflogs # no output git branch -a --contains <commit> # no output git show <commit> # still shows up 

Si no es un reflog y no es una sucursal, … ¡debe ser una label !

 git tag # showed several old tags created before the cleanup 

git tag -d <tagname> las tags con la label git tag -d <tagname> y rehice la limpieza, y las confirmaciones anteriores desaparecieron.

Tuve un problema similar. Ejecuté git branch --contains <commit> , y no devolvió ningún resultado como en la pregunta.

Pero incluso después de ejecutar

 git reflog expire --expire-unreachable=now --all git gc --prune=now 

mi compromiso todavía era accesible usando git show <commit> . Esto se debió a que se etiquetó uno de los commits en su "branch" separada / colgada. Eliminé la label, volví a ejecutar los commands anteriores y estaba dorado. git show <commit> returned fatal: bad object <commit> – exactamente lo que necesitaba. Espero que esto ayude a alguien más que estaba tan atrapado como yo.

git gc --prune=<date> para eliminar objects anteriores a hace dos semanas. Puede establecer una date más reciente. Pero, los commands git que crean objects sueltos generalmente ejecutarán git gc –auto (que poda los objects sueltos si su número excede el valor de la variable de configuration gc.auto).

¿Estás seguro de que deseas eliminar estos commits? La configuration pnetworkingeterminada de gc.auto garantizará que los objects sueltos no ocupen una cantidad irrazonable de memory, y almacenar objects sueltos durante un time es una buena idea. De esta forma, si se da count mañana de que su sucursal eliminada contenía una confirmación que necesitaba, puede recuperarla.

Accidentalmente, di con la misma situación y descubrí que mis depósitos contenían references a la confirmación inalcanzable, por lo que la confirmación supuestamente inalcanzable era alcanzable desde escondites.

Esto fue lo que hice para hacerlo realmente inalcanzable.

 git stash clear git reflog expire --expire-unreachable=now --all git fsck --unreachable git gc --prune=now