Diferencia en el tamaño de un repository local y bitbucket

Tengo un repository local. Comprobé el tamaño de la carpeta .git con el du -csh <foldername> . Es 168 mb. Lo empujé a mi repository bitbucket. Verifiqué que el tamaño del repository para download es de solo 134 mb.

¿Cómo es esto posible?

Primero, abordemos el tamaño del repository completo. (Vaya a la segunda sección de encabezado para omitir esta parte).

En general, los repositorys de "server puro" son lo que Git llama repositorys simples , que son repositorys sin tree de trabajo.

Recuerde que en cualquier repository de Git, 1 tiene:

  • cada compromiso que se haya realizado, almacenado en forma de solo Git, más
  • cada file asociado con estos commits, también almacenado en forma de solo Git, más
  • algunos datos generales misceláneos (tags, treees, nombres de reference, "información", ganchos, etc.).

Ninguno de estos 2 tiene la forma de "files con los que normalmente trabajas en tu computadora", por lo que si planeas hacer algo con un compromiso, que no sea enviarlo a otro Git, probablemente necesites un tree de trabajo. Los repositorys más --bare en los serveres simplemente transfieren confirmaciones a otros Gits (recibir y enviar), por lo que es una pérdida de espacio, y en realidad es contraproducente, mantener una copy de trabajo de una confirmación actual.

Debido a que los serveres omiten la copy de trabajo, generalmente se espera que los repositorys desnudos del lado del server sean más pequeños que los repositorys no expuestos del lado del cliente. Por lo tanto, el resultado observado no debe sorprender. Lo sorprendente es que a veces, el repository de tamaño de server es más grande . Hay muchas razones posibles para esto, lo más probable es que el código de compilation / recolección de basura aún no se haya ejecutado en el server. En algunos casos, es posible que necesite ayuda de quien ejecuta el server. Ver, por ejemplo, ¿Cómo networkingucir el tamaño de git repo en Bitbucket? Los detalles completos se adentran rápidamente en las malas hierbas de los formattings de file de package, windows de compression delta, directorys de objects alternativos (sitios como GitHub hacen un uso exhaustivo de este último para evitar que las horquillas ocupen mucho espacio) y demás.


1 Esto ignora deliberadamente los clones superficiales o de una sola twig, que truncan el historial en lugares específicos y, por lo tanto, omiten algunos o muchos commits y files.

2 De hecho, muchos de los files internos de Git son de text sin formatting, pero muchos no, y en cualquier caso, debe usar lo que Git llama los commands de plomería para manipularlos, si va a escribir su propio código para trabajar con Git. El uso de la API provista (los commands de fontanería) lo aísla de futuros cambios destinados a hacer que Git funcione mejor, más rápido, etc.


Pero tu .git es solo el repository simple

Usted comparó su file .git con su descarga. Ninguno de estos es o tiene un tree de trabajo, ¿por qué era más grande su directory .git ?

Ahora tenemos que meternos en esas malas hierbas, al less un poco.

Lo primero que debe saber es que Git tiene dos forms para cada object de Git : cada compromiso, cada "blob" (file) y cada label y tree anotado. Uno de estos es un formatting suelto , que simplemente está desinflado zlib. El otro está en un file de package , que está más comprimido.

Cuando trabajas en un repository de Git, creas nuevos objects sueltos. Git finalmente decide que hay demasiados objects sueltos que ocupan demasiado espacio y los empaqueta. Eso los hace más lentos de recuperar: tienen que ser encontrados y desempaquetados, en lugar de simplemente reunidos directamente y vueltos a inflar, pero ahora ocupan less espacio.

Segundo, cada vez que haces cosas en Git, agregas objects nuevos. Algunos de estos nunca se guardan de forma permanente. Estos objects (por lo general sueltos) son lo que Git llama sin reference: se hicieron con la intención de savelos, al less por un time y tal vez permanentemente, pero luego resultaron ser innecesarios, por lo que acaban de caer al suelo.

Además de esto, cada vez que rebase commits, en realidad los está copyndo y luego abandonando los originales. Pero Git mantiene los originales por al less 30 días por defecto, en caso de que cambies de opinión y los quieras de vuelta. Utiliza los reflog de Git para hacer esto.

Aquí es donde interviene el "recolector de basura" de Git, git gc . El recolector de basura, el Grim Reaper de Git, o el Grim Collector quizás, tiene varios trabajos, incluso para descubrir qué está envejeciendo de los reflogs y debería ser expulsado. Esto puede hacer que más objects se vuelvan sin reference (además de los que se crearon pero luego se volvió innecesario después de todo), por lo que luego encuentra objects sueltos sin reference y los "poda". Por último, se encarga de empaquetar los objects sueltos en el formatting de file de package más pequeño (pero de acceso más lento).

El recolector de basura se ejecuta automáticamente para usted cuando sea necesario; nunca deberías tener que ejecutarlo manualmente. Si tiene que ejecutarlo manualmente, eso es indicativo de una especie de error en Git (he leído algunos casos de esto, con scripts que sobrecargan la auto-poda del object suelto). Sin embargo, tenga en count que esto normalmente deja objects sueltos no referencedos durante al less 14 días, en caso de que algo siga trabajando para que se haga reference a ellos.

[Editar para agregar los últimos dos elementos que debería haber mencionado anteriormente:] Los serveres generalmente ejecutan git gc para empacar y limpiar después de cada inserción; y la versión descargable a veces se re -empaqueta en el lugar para hacerlo lo más pequeño posible, o al less, tan pequeño como "automáticamente posible" (a veces puede hacer que los files del package sean aún más pequeños ajustando los parameters de gc , aunque cuando primero Experimenté con Git. Seguí haciéndolos más grandes :-)).