Cuando agrego nuestro repositorio remoto como upstream e intento recuperarlo, falla como se muestra a continuación:
$ git fetch upstream
remote: Counting objects: 11901, done.
remote: aborting due to possible repository corruption on the remote side.
error: pack-objects died of signal 9
error: git upload-pack: git-pack-objects died with error.
fatal: git upload-pack: aborting due to possible repository corruption on the re
mote side.
fatal: protocol error: bad pack header
Entiendo que falla debido a que tiene archivos enormes en el repositorio (que sí tenemos), pero ¿por qué no falla cuando clono el mismo repositorio? Porque puedo clonar el repositorio con éxito. ¿No deberían empaquetarse los mismos objetos en el momento de una solicitud de clonación?
Para ampliar un poco la respuesta de VonC …
En primer lugar, puede ser útil tener en cuenta que signal 9
se refiere a SIGKILL
y tiende a ocurrir porque el control remoto en cuestión es un host Linux y el proceso está siendo destruido por Linux “OOM asesino” (aunque algunos sistemas que no son Linux se comportan de manera similar).
A continuación, hablemos de objetos y archivos de paquete. Un “objeto” de git es uno de los cuatro tipos de elementos que se encuentran en un repositorio de git: un “blob” (un archivo); un “árbol” (una lista de blobs, sus modos y sus nombres almacenados en un directorio: es decir, qué se convertirá en un directorio o carpeta cuando se descomprima una confirmación); una “confirmación” (que proporciona el autor de la confirmación, el mensaje y el árbol de nivel superior, entre otros datos); y una “etiqueta” (una etiqueta anotada). Los objetos se pueden almacenar como “objetos sueltos”, con un objeto en un archivo por sí mismo; pero estos pueden ocupar mucho espacio en disco, por lo que en su lugar se pueden “empaquetar”, muchos objetos en un archivo con compresión adicional agregada.
Hacer un paquete con una gran cantidad de objetos sueltos, hacer esta compresión, es (o al menos puede ser) una operación intensiva en CPU y memoria. La cantidad de memoria requerida depende de la cantidad de objetos y sus tamaños subyacentes: los archivos grandes requieren más memoria. Muchos archivos grandes ocupan mucha memoria.
A continuación, como señaló VonC, git clone
omite el intento de usar paquetes “delgados” (bueno, normalmente de todos modos). Esto significa que el servidor solo entrega los archivos de paquete que ya tiene. Esta es una operación de “memoria barata”: los archivos ya existen y el servidor solo necesita entregarlos.
Por otro lado, git fetch
intenta, si puede, evitar enviar muchos datos que el cliente ya tiene. Usando un protocolo “inteligente”, el cliente y el servidor entablan una especie de conversación, que puede pensar que es algo como esto:
- “Tengo el objeto A, que necesita B y C; ¿tienes B y C? También tengo D, E y F”.
- “Tengo B pero necesito C, y tengo D y E; por favor envíeme A, C y F”.
Así informado, el servidor extrae los objetos “interesantes”https://stackoverflow.com/”buscados” de los paquetes originales y luego intenta comprimirlos en un paquete nuevo (pero “delgado”). Esto significa que el servidor invocará git-pack-objects
.
Si el servidor tiene poca memoria (donde “bajo” es relativo a la cantidad que git-pack-objects
va a necesitar), es probable que invoque el “asesino OOM”. Ya que git-pack-objects
requiere mucha memoria, ese proceso es un candidato probable para que el “asesino OOM” mate. A continuación, verá, en el lado de su cliente, un mensaje sobre git-pack-objects
muriendo de signal 9
(SIGKILL
).
(Por supuesto, es posible que el asesino OOM del servidor elimine otra cosa por completo, como el servidor de la base de datos de errores. :-))
Puede depender del protocolo, pero Documentation/technical/pack-heuristics.txt
señala una primera diferencia entre clonar y fetch.
En la otra dirección, busca, git-fetch-pack
y git-clone-pack
invoca git-upload-pack
en el otro extremo (a través de ssh o hablando con el daemon).
Hay dos casos:
clone-pack
y fetch-pack
con -k
mantendrá el archivo del paquete descargado sin expandirse, por lo que no usamos la transferencia de paquetes delgados.
- De lo contrario, el paquete generado tendrá delta sin objeto base en el mismo paquete.
Pero fetch-pack
sin -k
explotará el paquete recibido en objetos individuales, por lo que automáticamente preguntamos upload-pack
para danos un paquete delgado si upload-pack
lo apoya
Entonces, en términos de protocolos, Documentation/technical/pack-protocol.txt
ilustra que una búsqueda puede devolver mucho más datos que un clon de git.