Tengo un repositorio de Git con muchas confirmaciones que no están bajo ninguna rama en particular, puedo git show
hacerlo, pero cuando trato de enumerar las ramas que las contienen, no informa nada.
Pensé que este es el problema del árbol / commits colgantes (como resultado de la rama -D), así que eliminé el repositorio, pero aún 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 accesible 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 enumerar todas las confirmaciones en un estado similar? ¿Cómo puedo eliminar confirmaciones como esas?
git
branch
git-dangling
Samer Buna
fuente
fuente
Respuestas:
Tenga en cuenta que las confirmaciones a las que se hace referencia desde su reflog se consideran accesibles.
Pase
--no-reflogs
para convencergit fsck
de mostrárselos.Una vez que sus entradas de reflog hayan caducado, esos objetos también serán limpiados por
git gc
.Caducidad está regulada por las
gc.pruneexpire
,gc.reflogexpire
ygc.reflogexpireunreachable
los ajustes. Cf.git help config
.Los valores predeterminados son todos bastante razonables.
fuente
git help glossary
define de esa manera ... mientras que su definición de "accesible" no se reduce de esa manera, por lo que son contradictorias. Es curioso, así que lo que dije es en realidad consistente con la confusión engitglossary
... No son los conceptos lo que confunden, sin embargo, solo la terminología. El punto es que los commits "colgantes" son aquellos a los que nada más apunta. ¿Ayudaría si digo "reflogs para commits que de otro modo serían inalcanzables" ...?master
estás en la sucursal , lo hacesgit commit
y obtienes un compromiso000001
. Entonces lo hacesgit commit --amend
, lo que te da compromiso000002
. Ya no hay etiquetas o ramas que apuntan000001
, y no puede verlo en su registro sin la--reflog
opción, pero si lo desea, aún puede hacerlogit checkout 000001
. Ahora la pregunta es, ¿es000001
un commit colgante , o un commit inalcanzable , o ninguno, o ambos?Para eliminar todos los commits colgantes y aquellos accesibles desde los reflogs, haga esto:
Pero asegúrese de que esto es lo que quiere. Le recomiendo que lea las páginas del manual, pero aquí está la esencia:
git gc
elimina objetos inalcanzables (commits, árboles, blobs (archivos)). 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 utilizamos lo
--prune=now
que significa "eliminar objetos inalcanzables que se crearon antes".Los objetos también se pueden alcanzar a través del registro. Mientras las sucursales registran el historial de algún proyecto, los registros registran el historial de estas sucursales. Si corrige, restablece, etc., las confirmaciones se eliminan del historial de la rama, pero git las mantiene en caso de que se dé cuenta de que cometió un error. Los registros son una forma conveniente de averiguar qué operaciones destructivas (y otras) se realizaron en una rama (o CABEZA), lo que facilita deshacer una operación destructiva.
Por lo tanto, también tenemos que eliminar los reflogs para eliminar todo lo que no sea accesible desde una rama. Lo hacemos expirando los
--all
registros. Una vez más Git guarda un poco de las reflogs a proteger a los usuarios por lo que de nuevo tenemos que decir que no hacerlo:--expire-unreachable=now
.Como utilizo principalmente el reflog para recuperarme de las operaciones destructivas, generalmente lo uso
--expire=now
, lo que elimina los reflogs por completo.fuente
git reflog expire --expire-unreachable=now --all
deja caer todos tus escondites!Tuve el mismo problema, aún después de seguir todos los consejos de este hilo:
Si no es un reflog y no una rama, ¡debe ser una etiqueta !
Eliminé las etiquetas
git tag -d <tagname>
y rehice la limpieza, y las viejas confirmaciones desaparecieron.fuente
probablemente solo necesita ser
para informar también sobre sucursales desde controles remotos
fuente
git push -d origin next
no ayudagit fetch --prune
hicieron el truco. pero en todas las respuestas me falta una comprobación de etiquetas que hacen referencia a esta confirmación. Todavía no sé cómo verificar las etiquetas con una confirmación (eliminé todas).git fsck --unreachable
lo tanto, en realidad se está comunicando a través de la red con el control remoto para descubrir qué compromisos son accesibles?git fsck --unreachable
no necesita comunicarse a través de la red con el control remoto para averiguar qué ramas remotas contienen qué confirmaciones. La información de la sucursal remota se almacena localmente, por ejemplo, en.git/refs/remotes/origin
(o enpacked-refs
).Tuve un problema similar Corrí
git branch --contains <commit>
, y no devolvió ningún resultado al igual que en la pregunta.Pero incluso después de correr
mi commit todavía estaba accesible usando
git show <commit>
. Esto se debió a que uno de los commits en su "rama" separada / colgada fue etiquetado. Quité la etiqueta, ejecuté los comandos anteriores nuevamente, y estaba dorado.git show <commit>
regreséfatal: bad object <commit>
, exactamente lo que necesitaba. Espero que esto ayude a alguien más que estaba tan atrapado como yo.fuente
Accidentalmente llegué a la misma situación y descubrí que mis escondites contienen referencias al compromiso inalcanzable, y por lo tanto, el supuesto compromiso inalcanzable era accesible desde los escondites.
Esto fue lo que hice para hacerlo verdaderamente inalcanzable.
fuente
git gc --prune=<date>
El valor predeterminado es podar objetos anteriores a hace dos semanas. Podrías establecer una fecha más reciente. Pero, los comandos git que crean objetos sueltos generalmente ejecutarán git gc --auto (que elimina objetos sueltos si su número excede el valor de la variable de configuración gc.auto).¿Estás seguro de que deseas eliminar estas confirmaciones? La configuración predeterminada de gc.auto asegurará que los objetos sueltos no ocupen una cantidad irrazonable de memoria, y generalmente es una buena idea almacenar objetos sueltos durante cierto tiempo. De esa manera, si se da cuenta mañana de que su rama eliminada contenía una confirmación que necesitaba, puede recuperarla.
fuente