¿Por qué git empujó tanta información?

Me pregunto qué hace git cuando impulsa los cambios, y por qué ocasionalmente empuja mucho más datos que los cambios que he hecho. Hice algunos cambios en dos files que agregaron alnetworkingedor de 100 líneas de código, less de 2k de text, me imagino.

Cuando fui a enviar esos datos hasta el origen, git convirtió eso en más de 47 MB ​​de datos:

git push -u origin foo Counting objects: 9195, done. Delta compression using up to 4 threads. Compressing objects: 100% (6624/6624), done. Writing objects: 100% (9195/9195), 47.08 MiB | 1.15 MiB/s, done. Total 9195 (delta 5411), reused 6059 (delta 2357) remote: Analyzing objects... (9195/9195) (50599 ms) remote: Storing packfile... done (5560 ms) remote: Storing index... done (15597 ms) To <<networkingacted>> * [new branch] foo -> foo Branch foo set up to track remote branch foo from origin. 

Cuando modifico mis cambios, (origin / master..HEAD) solo aparecieron los dos files y el commit I. ¿De dónde provienen los 47mb de datos?

Vi esto: cuando hago "git push", ¿qué significan las statistics? (Total, delta, etc.) y esto: Pnetworkingecir la cantidad de datos que se enviarán en un git push, pero eso realmente no me dice lo que está pasando … ¿Por qué el package / package sería enorme?

Cuando fui a enviar esos datos hasta el origen, git convirtió eso en más de 47 MB ​​de datos.

Parece que tu repository contiene una gran cantidad de datos binarys.


Primero, veamos qué hace git push.

git-push – Actualizar references remotas junto con objects asociados


¿Cuáles son esos associated objects ?

Después de cada confirmación, ejecutas un pack de tus datos en files llamados XX.pack && `XX.idx '


Una buena lectura sobre el embalaje está aquí

enter image description here

¿Cómo funciona git pack?

El formatting de file empaquetado .pack está diseñado para ser autónomo, de modo que se pueda desempaquetar sin más información.
Por lo tanto, cada object del que depende un delta debe estar presente dentro del package.

Un file de índice de package .idx se genera para un acceso rápido y aleatorio a los objects en el package.

Al colocar tanto el file de índice .idx como el pack empaquetado .pack en el subdirectory de pack de $GIT_OBJECT_DIRECTORY (o cualquiera de los directorys en $GIT_ALTERNATE_OBJECT_DIRECTORIES ), permite que Git lea del file del package.

Cuando git pack sus files lo hace de una manera inteligente por lo que será muy rápido para extraer datos.

Para lograr este git use package-heurística que básicamente busca una parte similar del contenido en tu package y almacenarlos como uno solo, es decir, si tienes el mismo encabezado (acuerdo de licencia, por ejemplo) en muchos files, git lo hará " encuéntralo y lo almacenarás una vez.

Ahora todos los files que incluyen esta licencia contendrán un puntero al código del encabezado. En este caso, git no tiene que almacenar el mismo código una y otra vez, por lo que el tamaño del package es mínimo.

Esta es una de las razones por las que no es una buena idea y no se recomienda almacenar files binarys en git ya que la posibilidad de tener similitudes es muy baja, por lo que el tamaño del package no será óptimo.

Git almacena tus datos en un formatting comprimido para networkingucir el espacio, así que de nuevo el binary tampoco será óptimo, ya que está comprimido (tamaño wize).


Aquí hay una muestra del blob de git usando la compression comprimida:

enter image description here

Me acabo de dar count de que hay un escenario muy realist que puede dar lugar a un empuje inusualmente grande.

¿Qué objects push envía? Que aún no existen en el server. O, más bien, que no detectó como existente. ¿Cómo verifica la existencia del object? Al comienzo de push, el server envía references (twigs y tags) que tiene. Entonces, por ejemplo, si tienen commits siguientes:

  CLIENT SERVER (foo) -----------> aaaaa1 | (origin/master) -> aaaaa0 (master) -> aaaaa0 | | ... ... 

Entonces el cliente obtendrá algo como /refs/heads/master aaaaa0 , y encontrará que debe enviar solo lo nuevo en commit aaaaa1 .

Pero, si alguien ha empujado algo a un maestro remoto, es diferente:

  CLIENT SERVER (foo) -----------> aaaaa1 (master) --> aaaaa2 | / (origin/master) -> aaaaa0 aaaaa0 | | ... ... 

Aquí, el cliente obtiene refs/heads/master aaaaa2 , pero no sabe nada sobre aaaaa2 , por lo que no puede deducir que aaaaa0 existe en el server. Entonces, en este caso simple de solo 2 twigs, se enviará toda la historia en lugar de solo incremental.

Es poco probable que esto ocurra en un proyecto desarrollado, desarrollado, que tiene tags y muchas twigs, algunas de las cuales se vuelven obsoletas y no se actualizan. Así que los usuarios pueden enviar un poco más, pero no se convierte en la gran diferencia como en su caso, y va sin manchas. Pero en equipos muy pequeños puede suceder más a menudo y la diferencia sería significativa.

Para evitarlo, puede ejecutar git fetch antes de pulsar. Entonces, en mi ejemplo, la confirmación aaaaa2 ya existiría en el cliente y git push foo sabría que no debería enviar aaaaa0 ni un historial anterior.

Lea aquí para la implementación de inserción en protocolo.