¿Cómo almacena git los files?

Acabo de empezar a aprender git y para hacerlo empecé a leer el libro de comunidad de Git , y en este libro dicen que SVN y CVS almacenan la diferencia entre los files y que git almacena una instantánea de todos los files.

Pero realmente no entiendo lo que quieren decir con una instantánea. ¿Git realmente hace una copy de todos los files en cada confirmación porque eso es lo que entendí de su explicación?

PD: Si alguien tiene una mejor fuente para aprender git, lo agradecería.

Git almacena para cada commit una copy completa de todos los files, excepto que, para el contenido ya presente en el repository de Git, la instantánea simplemente apuntará a dicho contenido en lugar de duplicarlo.
Eso también significa que varios files con el mismo contenido se almacenan solo una vez.

Entonces, una instantánea es básicamente una confirmación, refiriéndose al contenido de una estructura de directory.

Algunas buenas references son:

  • gitref.org

Le dices a Git que quieres save una instantánea de tu proyecto con el command git commit y básicamente registra un manifiesto de cómo son todos los files en tu proyecto en ese momento

  • git inmersión

El laboratorio 12 ilustra cómo get instantáneas anteriores

  • " Podrías haber inventado git (¡y quizás ya lo tengas!) "

  • ¿Qué es un git "Snapshot"?

  • Aprende GitHub


El libro de progit tiene la descripción más completa de una instantánea:

La principal diferencia entre Git y cualquier otro VCS (Subversion y amigos incluidos) es la forma en que Git piensa sobre sus datos.
Conceptualmente, la mayoría de los otros sistemas almacenan información como una list de cambios basados ​​en files. Estos sistemas (CVS, Subversion, Perforce, Bazaar, etc.) piensan en la información que guardan como un set de files y los cambios realizados en cada file a lo largo del time.

VCS basado en delta

Git no piensa ni almacena sus datos de esta manera. En cambio, Git piensa que sus datos se parecen más a un set de instantáneas de un mini sistema de files.
Cada vez que se compromete o guarda el estado de su proyecto en Git, básicamente toma una image de cómo se ven todos los files en ese momento y almacena una reference a esa instantánea.
Para ser eficiente, si los files no han cambiado, Git no almacena el file nuevamente, solo un enlace al file idéntico anterior que ya ha almacenado.
Git piensa en sus datos más como sigue:

VCS basado en instantáneas

Esta es una distinción importante entre Git y casi todos los demás VCS. Hace que Git reconsidere casi todos los aspectos del control de versiones que la mayoría de los demás sistemas copyron de la generación anterior. Esto hace que Git se parezca más a un mini sistema de files con algunas herramientas increíblemente potentes creadas encima, en lugar de simplemente un VCS.


Jan Hudec agrega este importante comentario :

Si bien eso es cierto e importante en el nivel conceptual, NO es cierto en el nivel de almacenamiento.
Git usa deltas para el almacenamiento .
No solo eso, sino que es más eficiente que cualquier otro sistema. Debido a que no mantiene el historial por file, cuando quiere hacer la compression delta , toma cada blob, selecciona algunos blobs que probablemente sean similares (utilizando heurística que incluye la aproximación más cercana de la versión anterior y algunos otros), intenta generar los deltas y elige el más pequeño. De esta forma, puede (a menudo, depende de la heurística) aprovechar otros files similares o versiones anteriores que son más similares que las anteriores. El parámetro "package de window" permite el performance comercial para la calidad de compression delta. El valor pnetworkingeterminado (10) generalmente arroja resultados decentes, pero cuando el espacio es limitado o para acelerar las transferencias de networking, git gc --aggressive usa el valor 250, lo que lo hace funcionar muy lento, pero proporciona compression adicional para los datos del historial.

Git almacena lógicamente cada file en su SHA1. Lo que esto significa es que si tiene dos files con exactamente el mismo contenido en un repository (o si cambia el nombre de un file), solo se almacena una copy.

Pero esto también significa que cuando modifica una pequeña parte de un file y confirma, se almacena otra copy del file. La forma en que git resuelve esto es usando files de package. De vez en cuando, todos los files "sueltos" (en realidad, no solo files, sino también objects que contienen información de compromiso y de directory) de un repository se recostackn y comprimen en un file de package. El file del package está comprimido usando zlib. Y los files similares también están comprimidos delta.

El mismo formatting también se usa al tirar o empujar (al less con algunos protocolos), por lo que no es necesario recomprimir nuevamente esos files.

El resultado de esto es que un repository de git, que contiene toda la copy de trabajo sin comprimir, los files recientes sin comprimir y los files comprimidos más antiguos suele ser relativamente pequeño, más pequeño que el doble del tamaño de la copy de trabajo. Y esto significa que es más pequeño que el repository SVN con los mismos files, aunque SVN no almacena el historial localmente.

Sí, git sí hace una copy de los files. La filosofía es que en la mayoría de las situaciones, el espacio en disco es esencialmente gratuito en grandes cantidades.

Esta es la razón por la cual los resources grandes (videos, grabaciones de sonido, etc.) a menudo no son rastreados cuando se usa git. Ver, por ejemplo, esta discusión .

PD: Lars Vogel presenta una buena introducción a git aquí .

Las respuestas anteriores son bastante interesantes, pero me gustaría agregar un pequeño concepto más pequeño conocido como encoding delta. La eficiencia se guarda hasta que se escribe el file del package. Los objects sueltos se escriben en formatting comprimido, pero no delta, en el momento de cada confirmación.