¿Cómo almacena git los archivos?

225

Recién comencé a aprender git y para hacerlo comencé a leer el Git Community Book , y en este libro dicen que SVN y CVS almacenan la diferencia entre archivos y que git almacena una instantánea de todos los archivos.

Pero realmente no entendí lo que quieren decir con instantánea. ¿Realmente git hace una copia de todos los archivos 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.

mteffaha
fuente
20
Aquí hay una publicación brillante que explica en detalle cómo funciona git. Lo que está buscando es probablemente el § sobre la base de datos de objetos.
greg0ire
Excelente artículo que contiene enlaces a otros excelentes recursos. Me he divertido con estos durante un par de horas.
mihai
2
Encontré este artículo realmente agradable que describe git de adentro hacia afuera: maryrosecook.com/blog/post/git-from-the-inside-out
Sumudu

Respuestas:

275

Git incluye para cada confirmación una copia completa de todos los archivos, excepto que, para el contenido ya presente en el repositorio de Git, la instantánea simplemente apuntará a dicho contenido en lugar de duplicarlo.
Eso también significa que varios archivos con el mismo contenido se almacenan solo una vez.

Entonces, una instantánea es básicamente una confirmación, que se refiere al contenido de una estructura de directorio.

Algunas buenas referencias son:

Le dice a Git que desea guardar una instantánea de su proyecto con el comando git commit y básicamente registra un manifiesto de cómo se ven todos los archivos en su proyecto en ese momento

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


El libro 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 acerca de sus datos.
Conceptualmente, la mayoría de los otros sistemas almacenan información como una lista de cambios basados ​​en archivos. Estos sistemas (CVS, Subversion, Perforce, Bazaar, etc.) piensan en la información que mantienen como un conjunto de archivos y los cambios realizados en cada archivo a lo largo del tiempo.

VCS basado en delta

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

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 otros sistemas copiaron de la generación anterior. Esto hace que Git se parezca más a un mini sistema de archivos con algunas herramientas increíblemente poderosas construidas sobre él, 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 archivo, cuando quiere hacer una compresión delta, toma cada blob, selecciona algunos blobs que probablemente sean similares (usando la heurística que incluye la aproximación más cercana de la versión anterior y algunas otras), intenta generar los deltas y elige el más pequeño. De esta forma, puede (a menudo, depende de la heurística) aprovechar otros archivos similares o versiones anteriores que son más similares a las anteriores. El parámetro "ventana de paquete" permite el rendimiento comercial para la calidad de compresión delta. El valor predeterminado (10) generalmente proporciona resultados decentes, pero cuando el espacio es limitado o para acelerar las transferencias de red, git gc --aggressiveutiliza el valor 250, lo que hace que funcione muy lento, pero proporciona una compresión adicional para los datos del historial.

VonC
fuente
44
@JanHudec buen punto. He incluido tu comentario en la respuesta para mayor visibilidad.
VonC
1
¿Alguien conoce el término informático para el patrón de almacenamiento similar a Git, también conocido como almacén de valor basado en hash? (o algo similar)
Joannes Vermorel
34
En el contexto de la pregunta real del PO, el primer párrafo parece realmente engañoso. No es hasta que llegue al inciso final que nos enteramos de que, oh sí, hecho de Git hace "tienda de [...] diferencias entre los archivos. Realmente deseo que esa información se encuentra en posición encima de la tapa y no tan profundamente enterrado. Dicho esto, gracias a menos incluir la historia real en algún lugar de tu respuesta;)
Josh O'Brien
1
@NickVolynkin ¡Genial! Me alegra que esas respuestas encuentren una audiencia más amplia.
VonC
1
Otro buen libro: Git From The Bottom Up: ftp.newartisans.com/pub/git.from.bottom.up.pdf
Jonas Berlin
46

Git almacena lógicamente cada archivo bajo su SHA1. Esto significa que si tiene dos archivos con exactamente el mismo contenido en un repositorio (o si cambia el nombre de un archivo), solo se almacena una copia.

Pero esto también significa que cuando modifica una pequeña parte de un archivo y confirma, se almacena otra copia del archivo. La forma en que git resuelve esto es mediante el uso de archivos de paquete. De vez en cuando, todos los archivos "sueltos" (en realidad, no solo los archivos, sino también los objetos que contienen información de confirmación y directorio) de un repositorio se recopilan y comprimen en un archivo de paquete. El archivo del paquete se comprime usando zlib. Y archivos similares también están comprimidos en delta.

El mismo formato también se usa cuando se tira o empuja (al menos con algunos protocolos), por lo que esos archivos no tienen que volver a comprimirse.

El resultado de esto es que un repositorio git, que contiene toda la copia de trabajo sin comprimir, los archivos recientes sin comprimir y los archivos antiguos comprimidos, generalmente es relativamente pequeño, dos veces más pequeño que el tamaño de la copia de trabajo. Y esto significa que es más pequeño que el repositorio SVN con los mismos archivos, aunque SVN no almacena el historial localmente.

svick
fuente
1
ah, así que mercurial es más eficiente en el espacio
Ben