tag remote rama origin example clonar git branch git-dangling

remote - git push tag



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

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

Pensé que este es el problema de commit / tree colgando (como resultado de la rama -D), así que eliminé el repositorio, 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 rama como

$ git branch --contains 793db7f272ba4bbdd1e32f14410a52a412667042

no da salida

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


Sin salida, nada colgando (¿verdad?)

Tenga en cuenta que las confirmaciones a las que se hace referencia desde su reflog se consideran alcanzables.

¿Cuál es exactamente el estado de ese compromiso? ¿Cómo puedo hacer una lista 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 entradas de reflog, esos objetos 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 predeterminados son todos bastante razonables.


Accidentalmente pulsé la misma situación y descubrí que mis depósitos contienen referencias a la confirmación inalcanzable, y por lo tanto, la supuesta obligación 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


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 objetos inalcanzables (commits, trees, blobs (files)). Un objeto es inalcanzable si no es parte del historial de alguna rama. En realidad es un poco más complicado:

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

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

Los objetos 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 ramas. Si modificas, restableces, etc., las confirmaciones se eliminan del historial de la sucursal, pero git las conserva en caso de que te des cuenta de que cometiste un error. Los Reflogs son una forma conveniente de descubrir qué operaciones destructivas (y otras) se realizaron en una rama (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, suelo usar --expire=now lugar, lo que elimina por completo los reflogs.


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 etiqueta !

git tag # showed several old tags created before the cleanup

git tag -d <tagname> las etiquetas con la etiqueta 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 etiqueta, volví a ejecutar los comandos 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 objetos anteriores a hace dos semanas. Puede establecer una fecha más reciente. Pero, los comandos git que crean objetos sueltos generalmente ejecutarán git gc --auto (que poda los objetos sueltos si su número excede el valor de la variable de configuración gc.auto).

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


git branch --contains 793db7f272ba4bbdd1e32f14410a52a412667042

Probablemente solo necesite ser

git branch -a --contains 793db7f272ba4bbdd1e32f14410a52a412667042

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