tutorial repositorio que lista comandos actualizar git

repositorio - lista de comandos git



Cómo eliminar blobs no referenciados de mi git repo (10)

Tengo un repositorio GitHub que tenía dos ramas: master y release.

La rama de publicación contenía archivos de distribución binarios que contribuían a un tamaño de repo muy grande (> 250 MB), así que decidí limpiar las cosas.

Primero borré la rama de liberación remota, a través de git push origin :release

Luego borré la rama de publicación local. Primero probé git branch -d release , pero git dijo "error: la rama ''release'' no es un antecesor de tu HEAD actual." lo cual es cierto, entonces hice git branch -D release para forzar que se elimine.

Pero mi tamaño de repositorio, tanto a nivel local como en GitHub, todavía era enorme. Entonces corrí a través de la lista habitual de comandos de git, como git gc --prune=today --aggressive , sin suerte.

Siguiendo las instrucciones de Charles Bailey en SO 1029969 , pude obtener una lista de SHA1 para las manchas más grandes. Luego utilicé el script de SO 460331 para encontrar los blobs ... y los cinco más grandes no existen, aunque se encuentran blobs más pequeños, así que sé que el script está funcionando.

Creo que estos blogs son los binarios de la rama de lanzamiento, y de alguna manera se quedaron después de la eliminación de esa rama. ¿Cuál es la forma correcta de deshacerse de ellos?


... y sin más preámbulos, permítanme presentarles este útil script, git-gc-all , que garantiza eliminar toda su basura git hasta que puedan aparecer variables de configuración adicionales:

git -c gc.reflogExpire=0 -c gc.reflogExpireUnreachable=0 -c gc.rerereresolved=0 / -c gc.rerereunresolved=0 -c gc.pruneExpire=now gc "$@"

También es posible que tengas que ejecutar algo como esto primero, ¡oh cariño, git es complicado!

git remote rm origin rm -rf .git/refs/original/ .git/refs/remotes/ .git/*_HEAD .git/logs/ git for-each-ref --format="%(refname)" refs/original/ | xargs -n1 --no-run-if-empty git update-ref -d

Puse todo esto en un guión, aquí:

http://sam.nipl.net/b/git-gc-all-ferocious

editar: es posible que también deba eliminar algunas etiquetas, gracias a Zitrax:

git tag | xargs git tag -d


A veces, la razón por la que "gc" no sirve de mucho es que hay una base de datos sin terminar o un alijo basado en una confirmación anterior.


Antes de hacer git filter-branch y git gc , debe revisar las etiquetas que están presentes en su repositorio. Cualquier sistema real que tenga etiquetado automático para cosas como la integración continua y las implementaciones hará que los objetos no deseados continúen siendo referenciados por estas etiquetas, por lo tanto, gc no puede eliminarlos y todavía te preguntarás por qué el tamaño del repositorio sigue siendo tan grande.

La mejor manera de deshacerse de todas las cosas no deseadas es ejecutar git-filter & git gc y luego enviar master a un nuevo repositorio desnudo. El nuevo repositorio desnudo tendrá el árbol limpio.


Cada vez que su HEAD se mueve, git rastrea esto en el reflog . Si eliminas commits, aún tienes "commits pendientes" porque el reflog todavía hace referencia a reflog durante ~ 30 días. Esta es la red de seguridad cuando elimina commits por accidente.

Puedes usar el comando git reflog eliminar commits específicos, reempaquetar, etc., o solo el comando de alto nivel:

git gc --prune=now


Como se describe here , simplemente use

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

git reflog expire --expire-unreachable=now --all elimina todas las referencias de commits inalcanzables en reflog .

git gc --prune=now elimina los commits ellos mismos.

Atención : solo usar git gc --prune=now no funcionará, ya que las confirmaciones aún se referencian en el reflog. Por lo tanto, borrar el reflog es obligatorio.


Como se menciona en esta respuesta SO , git gc realidad puede aumentar el tamaño del repositorio.

Ver también este hilo

Ahora git tiene un mecanismo de seguridad para no eliminar objetos sin referencia de inmediato cuando se ejecuta '' git gc ''.
Por defecto, los objetos sin referencia se guardan por un período de 2 semanas. Esto es para que sea más fácil para usted recuperar ramas o commits accidentalmente eliminados, o para evitar una carrera donde un objeto recién creado en proceso de ser pero aún no referenciado podría ser eliminado por un proceso '' git gc '' que se ejecuta en paralelo.

Entonces, para otorgar ese período de gracia a objetos empaquetados pero no referenciados, el proceso de reempaque empuja a esos objetos sin referencia fuera del paquete a su forma suelta para que puedan envejecerse y finalmente podarse.
Sin embargo, los objetos que se vuelven sin referencias generalmente no son tan numerosos. Tener 404855 objetos sin referencia es bastante, y enviar esos objetos en primer lugar a través de un clon es una estupidez y un desperdicio completo del ancho de banda de la red.

De todos modos ... Para resolver su problema, simplemente necesita ejecutar '' git gc '' con el argumento --prune=now para deshabilitar ese período de gracia y deshacerse de esos objetos sin referencia de inmediato (seguro solo si no están tomando otras actividades de git colocar al mismo tiempo que debería ser fácil de asegurar en una estación de trabajo).

Y por cierto, usando '' git gc --aggressive '' con una versión posterior de git (o '' git repack -a -f -d --window=250 --depth=250 '')

El mismo hilo menciona :

git config pack.deltaCacheSize 1

Eso limita el tamaño de la memoria caché delta a un byte (deshabilitándolo) en lugar del valor predeterminado de 0, lo que significa ilimitado. Con eso puedo volver a empaquetar ese repositorio usando el comando git repack anterior en un sistema x86-64 con 4GB de RAM y usando 4 hilos (este es un quad core). Sin embargo, el uso de la memoria residente crece a casi 3.3GB.

Si su máquina es SMP y no tiene suficiente RAM, puede reducir el número de hilos a solo uno:

git config pack.threads 1

Además, puede limitar aún más el uso de la memoria con el --window-memory argument para '' git repack ''.
Por ejemplo, el uso de --window-memory=128M debe mantener un límite superior razonable en el uso de la memoria de búsqueda delta, aunque esto puede dar como resultado una combinación delta menos óptima si el repositorio contiene muchos archivos grandes.

En el frente de la rama de filtro, puede considerar (con precaución) este script

#!/bin/bash set -o errexit # Author: David Underhill # Script to permanently delete files/folders from your git repository. To use # it, cd to your repository''s root and then run the script with a list of paths # you want to delete, e.g., git-delete-history path1 path2 if [ $# -eq 0 ]; then exit 0 fi # make sure we''re at the root of git repo if [ ! -d .git ]; then echo "Error: must run this script from the root of a git repository" exit 1 fi # remove all paths passed as arguments from the history of the repo files=$@ git filter-branch --index-filter "git rm -rf --cached --ignore-unmatch $files" HEAD # remove the temporary history git-filter-branch otherwise leaves behind for a long time rm -rf .git/refs/original/ && git reflog expire --all && git gc --aggressive --prune


Intenta usar git-filter-branch : no elimina grandes blobs, pero puede eliminar los archivos grandes que especifiques de todo el repositorio. Para mí, reduce el tamaño del repositorio de cientos MB a 12 MB.


Para agregar otro consejo, no se olvide de usar git remote podar para eliminar las ramas obsoletas de sus controles remotos antes de usar git gc

puedes verlos con git branch -a

A menudo es útil cuando traes de github y repositorios bifurcados ...


Puedes usar git forget-blob .

El uso es bastante simple. git forget-blob file-to-forget . Puede obtener más información aquí

https://ownyourbits.com/2017/01/18/completely-remove-a-file-from-a-git-repository-with-git-forget-blob/

Desaparecerá de todas las confirmaciones de tu historial, reflog, etiquetas, etc.

Me encuentro con el mismo problema de vez en cuando, y cada vez que tengo que volver a esta publicación y a otras, es por eso que automaticé el proceso.

Créditos a colaboradores como Sam Watkins


git gc --prune=now , o git prune --expire now bajo nivel git prune --expire now .