git es muy, muy lento al rastrear archivos binarios grandes

83

Mi proyecto tiene seis meses y git es muy, muy lento. Realizamos un seguimiento de alrededor de 30 archivos que tienen un tamaño de 5 MB a 50 MB. Esos son archivos binarios y los mantenemos en git. Creo que esos archivos hacen que git sea lento.

¿Hay alguna manera de eliminar todos los archivos de tamaño> 5 MB del repositorio? Sé que perdería todos estos archivos y eso me parece bien.

Idealmente, me gustaría un comando que enumerara todos los archivos grandes (> 5 MB). Puedo ver la lista y luego digo que está bien, elimine esos archivos y haga que git sea más rápido.

Debo mencionar que git es lento no solo en mi máquina, sino que la implementación de la aplicación en el entorno de prueba ahora está demorando alrededor de 3 horas.

Entonces, la solución debería ser algo que afecte al servidor y no solo a los usuarios del repositorio.

Nick Vanderbilt
fuente
4
Puede intentar usar git del git-bigfilesproyecto
Jakub Narębski
1
es posible que desee intentar usar algo como git-Annex para administrar archivos binarios. git-annex.branchable.com
Jed Schneider
En caso de que sea útil para alguien, permítanme agregar que mi versión Cygwin de git estaba colgando de rebases. Cuando usé Git-Bash, el mismo repositorio no tuvo problemas.
Sridhar Sarnobat
Me pregunto si sigue siendo así. Espero que desactiven la compresión para todo aquello en que el efecto de compresión esté por debajo del 50% (o cualquier otro X% elegible). En algún momento, la velocidad supera claramente al espacio del hardware.
Trilarion

Respuestas:

125

¿Recolecta basura?

git gc

Esto hace una diferencia significativa en la velocidad, incluso para repositorios pequeños.

kubi
fuente
8
Esto se hace automáticamente cuando hay demasiado desorden. Dudo que realmente ayude al OP.
Cascabel
@Jefromi, ¿eso es nuevo? Acabo de actualizar a 1.7.1 ayer, pero antes de eso, la versión que estaba usando definitivamente no se ejecutaba automáticamente gc.
kubi
@kubi: Bueno, no ha existido desde siempre, pero no es exactamente nuevo: se ha invocado desde commit, merge, am y rebase desde caf9de2 (14 de septiembre de 2007), o en la versión estable v1.5.4 (1 de febrero de 2008 ).
Cascabel
1
Pensándolo bien, git gcno es posible que lo llamen commity merge, de lo contrario git fsck --unreachable, nunca devolvería nada.
kubi
4
Lo encontré. El número predeterminado de objetos sueltos antes de que se gcejecute automáticamente es 6700, lo que explica por qué nunca lo he visto ejecutarse.
kubi
79

Explicación

Git es realmente bueno en grandes historias de archivos de texto pequeños porque puede almacenarlos y sus cambios de manera eficiente. Al mismo tiempo, git es muy malo en archivos binarios y almacenará ingenuamente copias separadas del archivo ( por defecto, al menos ). El repositorio se vuelve enorme y luego se vuelve lento, como ha observado.

Este es un problema común entre los DVCS, agravado por el hecho de que descarga cada versión de cada archivo ("el repositorio completo") cada vez que clona. Los chicos de Kiln están trabajando en un complemento para tratar estos archivos grandes más como Subversion, que solo descarga versiones históricas bajo demanda.

Solución

Este comando enumerará todos los archivos en el directorio actual de tamaño> = 5 MB.

find . -size +5000000c 2>/dev/null -exec ls -l {} \;

Si desea eliminar los archivos de todo el historial del repositorio, puede usar esta idea con git filter-branchpara recorrer el historial y deshacerse de todos los rastros de archivos grandes. Después de hacer esto, todos los nuevos clones del repositorio serán más eficientes. Si desea optimizar un repositorio sin clonarlo, encontrará instrucciones en la página de manual (consulte "Lista de verificación para reducir un repositorio").

git filter-branch --index-filter \
    'find . -size +5000000c 2>/dev/null -exec git rm --cached --ignore-unmatch {} \;'

Una advertencia : esto hará que su repositorio sea incompatible con otros clones, porque los árboles y los índices tienen diferentes archivos registrados; ya no podrás empujarlos ni tirar de ellos.

Andrés Jaan Tack
fuente
4
Nota: esa es la versión de Unix / Linux de find, no la de Windows find.exe.
Craig Trader
1
+1. Es posible que desee enviar la salida de finda un archivo primero, verifique la lista y luego use git rm, en caso de que haya resultados falsos. Alternativamente, verifique git statusdespués de eliminar archivos grandes y utilícelo git checkout HEAD <file>para recuperar los archivos eliminados por error.
Cascabel
2
Creo que su comentario de que git "almacena copias separadas por defecto" está al revés. De acuerdo con la cadena de correo electrónico a la que se vinculó ( thread.gmane.org/gmane.comp.version-control.git/146957/… ) de forma predeterminada, git intenta diferenciar los archivos binarios, y eso es lo que está causando el problema; no el almacenamiento.
Alexander Bird
16

Aquí hay una revisión censurada destinada a ser menos negativa e inflamatoria:

Git tiene una debilidad bien conocida cuando se trata de archivos que no son archivos de texto línea por línea. Actualmente no hay una solución y el equipo central de git no ha anunciado planes para abordar esto. Existen soluciones alternativas si su proyecto es pequeño, digamos, 100 MB aproximadamente. Existen ramas del proyecto git para abordar este problema de escalabilidad, pero estas ramas no están maduras en este momento. Algunos otros sistemas de control de revisiones no tienen este problema específico. Debe considerar este problema como solo uno de los muchos factores al decidir si seleccionar git como su sistema de control de revisiones.

Juan
fuente
8
"Git tiene una debilidad bien conocida ..." - cita requerida
Nav
6
Lo sé. que necesita citas cuando es de conocimiento común real. simplemente no uses git para binario. utilizar la gestión de activos obligatoria o especializada.
v.oddou
1
@ v.oddou Bueno, hay una diferencia entre "lo sé" y "su conocimiento común real". Esto es que no todo el mundo lo sabe y probablemente ni siquiera sea del todo cierto. Entonces, cualquier tipo de cita mejora esta respuesta. Está bien, pero seguramente no sobresaliente y respaldado.
Trilarion
2
Bueno, no para echar más leña al fuego, pero si haces una búsqueda en Google de "git y archivos binarios lentos", se encuentran muchos enlaces que informan a los usuarios que tienen problemas para administrar archivos binarios en git. Además, los desarrolladores que usan un SCM u otro conocen las fortalezas y debilidades de cada sistema ... así que, git ha desarrollado una reputación de volverse realmente lento cuando los archivos binarios se lanzan a un repositorio.
AhiyaHiya
está en todos los recursos introductorios que he usado que git es malo con archivos binarios. git-Annex existe para solucionar este problema. git es genial, pero no para datos binarios. Sería bueno vincular a las bifurcaciones que agregan características binarias, para que las personas puedan respaldar el trabajo.
fuzzyTew
15

No hay nada específico sobre los archivos binarios y la forma en que git los maneja. Cuando agrega un archivo a un repositorio de git, se agrega un encabezado y el archivo se comprime con zlib y se renombra después del hash SHA1. Esto es exactamente lo mismo independientemente del tipo de archivo. No hay nada en la compresión zlib que lo haga problemático para los archivos binarios.

Pero en algunos puntos (presionando, gc) Git comienza a considerar la posibilidad de comprimir el contenido delta. Si git encuentra archivos que son similares (nombre de archivo, etc.), los está colocando en la RAM y comienza a comprimirlos. Si tiene 100 archivos y cada uno de ellos llega a 50 Mb, intentará colocar 5 GB en la memoria al mismo tiempo. A esto hay que añadir más para que las cosas funcionen. Es posible que su computadora no tenga esta cantidad de RAM y comience a intercambiarse. El proceso lleva tiempo.

Puede limitar la profundidad de la compresión delta para que el proceso no use tanta memoria pero el resultado sea una compresión menos eficiente. (core.bigFileThreshold, atributo delta, pack.window, pack.depth, pack.windowMemory, etc.)

Así que hay muchas cosas que puedes hacer para que git funcione muy bien con archivos grandes.

martín
fuente
4
Consulte aquí para obtener una explicación de cómo deshabilitar esos intentos "delta" para que no se produzcan.
Alexander Bird
6

Una forma de acelerar las cosas es usar la --depth 1bandera. Consulte la página del manual para obtener más detalles. No soy un gran gurú, pero creo que esto dice haz el equivalente de a p4 geto an svn get, es decir, te da solo los archivos más recientes en lugar de "dame todas las revisiones de todos los archivos de todo el tiempo", que es que git clonehace.

David
fuente
1
Esto no le permite empujar desde el repositorio, por lo que es de utilidad limitada.
Martin C. Martin
4

¿Le has dicho a git que esos archivos son binarios?

por ejemplo, agregado *.ext binarya su repositorio.gitattributes

sml
fuente
Supongo que decirle a git que los archivos son binarios acelera las cosas.
Nick Vanderbilt
podría serlo si la heurística de git no puede decir que un archivo es binario automáticamente.
sml
2

He estado ejecutando Git desde 2008 tanto en Windows como en GNU / Linux y la mayoría de los archivos que rastreo son archivos binarios. Algunos de mis repositorios son de varios GB y contienen Jpeg y otros medios. Tengo muchas computadoras en casa y en el trabajo que ejecutan Git.

Nunca he tenido los síntomas que se describen en la publicación original. Pero hace solo un par de semanas instalé MsysGit en una vieja computadora portátil Win-XP y casi todo lo que hice, detuvo a git. Incluso la prueba con solo dos o tres archivos de texto pequeños fue ridículamente lenta. Estamos hablando de 10 minutos para agregar un archivo de menos de 1k ... parece que los procesos de git se mantuvieron vivos para siempre. Todo lo demás funcionó como se esperaba en esta computadora.
Bajé de la última versión a 1.6 algo y los problemas desaparecieron ...
Tengo otras computadoras portátiles de la misma marca, también con Win-XP instalado por el mismo departamento de TI de la misma imagen, donde Git funciona bien independientemente de la versión. .. Entonces debe haber algo extraño con esa computadora en particular.

También he hecho algunas pruebas con archivos binarios y compresión. Si tiene una imagen BMP y le hace pequeños cambios y los confirma, git gc se comprimirá muy bien. Entonces mi conclusión es que la compresión no depende de si los archivos son binarios o no.

martín
fuente
-2

Simplemente configure los archivos para que se ignoren. Vea el enlace a continuación:

http://help.github.com/git-ignore/

Joshlrogers
fuente
@Jefromi en realidad, si miras el enlace que publiqué, verás que hay instrucciones en el segundo párrafo que le dicen exactamente qué hacer en ese caso.
Joshlrogers
14
Cierto. Pero el contenido directo de su respuesta es "ignorar los archivos", no "eliminar los archivos del seguimiento y luego ignorarlos". Por lo general, es mejor escribirlo aquí que vincularlo a otro sitio.
Cascabel
-24

Eso es porque git no es escalable.

Esta es una limitación seria en git que es ahogada por la defensa de git. Busque en las listas de correo de git y encontrará cientos de usuarios que se preguntan por qué solo unos escasos 100 MB de imágenes (por ejemplo, para un sitio web o una aplicación) ponen a git de rodillas. El problema parece ser que casi todo git se basa en una optimización a la que se refieren como "empaquetado". Desafortunadamente, el empaquetado es ineficiente para todos los archivos de texto, excepto para los más pequeños (es decir, el código fuente). Peor aún, se vuelve cada vez menos eficiente a medida que aumenta la historia.

Es realmente un defecto vergonzoso en git, que se promociona como "rápido" (a pesar de la falta de evidencia), y los desarrolladores de git lo saben muy bien. ¿Por qué no lo han arreglado? Encontrará respuestas en la lista de correo de git de los desarrolladores de git que no reconocerán el problema porque los documentos de Photoshop (* .psd) tienen un formato propietario. Sí, es realmente tan malo.

Aquí está el resultado:

Use git para proyectos pequeños, solo de código fuente, para los que no tiene ganas de configurar un repositorio separado. O para proyectos pequeños de solo código fuente en los que desea aprovechar el modelo de desarrollo descentralizado de copia de repositorio completo de git. O cuando simplemente quiere aprender una nueva herramienta. Todas estas son buenas razones para usar git, y siempre es divertido aprender nuevas herramientas.

No uses git si tienes una base de código grande, binarios, un historial enorme, etc. Solo uno de nuestros repositorios es un TB. Git no puede manejarlo. VSS, CVS y SVN lo manejan bien. (Sin embargo, SVN se hincha).

Además, dale a Git tiempo para madurar. Todavía es inmaduro, pero tiene mucho impulso. Con el tiempo, creo que la naturaleza práctica de Linus superará a los puristas de OSS, y git finalmente se podrá utilizar en un campo más amplio.

Juan
fuente
15
Esta respuesta es realmente demasiado negativa e inflamatoria. Sí, git tiene problemas de escalabilidad con archivos binarios . Es bastante escalable y rápido para el código. Hay mucha evidencia de la velocidad (a pesar de su afirmación de lo contrario), incluso sin tener en cuenta el hecho de que CVS / SVN requiere acceso a la red en lugar de acceso al disco para muchas operaciones. Hay muchos proyectos grandes con grandes historias que utilizan git.
Cascabel
8
Y ... ¿estás insistiendo en lo de Photoshop? No voy a perder el tiempo escribiendo una respuesta detallada, pero si después de leer el hilo completo thread.gmane.org/gmane.comp.version-control.git/146957/… (tal vez esté molesto porque el John en ¿El hilo eres tú?), Veo muchas respuestas razonables sobre la mejor manera de manejar esto con el git actual, cómo podría abordarse en el futuro y por qué no es su primera prioridad.
Cascabel
14
Sí, no creo que tengas razón aquí. Git funciona manera demasiado bien para el núcleo de Linux para merecer una desdeñosa, "no es escalable."
Andres Jaan Tack
1
Este comentario sería más creíble si tuviera enlaces o datos para respaldarlo. Por cierto, ¿qué opinas de mercurial?
vy32
3
Tal vez no exprese una opinión popular, pero creo que la votación en contra fue más excesiva en su 'negatividad' que la Respuesta del OP. Debemos alentar el disenso, no acumularnos solo porque a alguien no le gusta el sabor de control de versiones del año. GIT realmente no es adecuado para rastrear archivos binarios. Pero funciona muy bien para el código fuente, es la intención principal, por lo que funciona de maravilla en el kernel de Linux.
dyasta