Lo confuso está aquí:
Git nunca los ve como archivos individuales. Git piensa todo como el contenido completo.
Git a menudo usa hashes de 160 bits en lugar de objetos en su propio repositorio. Un árbol de archivos es básicamente una lista de nombres y hashes asociados con el contenido de cada uno (más algunos metadatos).
Pero el hash de 160 bits identifica de forma exclusiva el contenido (dentro del universo de la base de datos git). Entonces, un árbol con hashes como contenido incluye el contenido en su estado.
Si cambia el estado del contenido de un archivo, su hash cambia. Pero si su hash cambia, el hash asociado con el contenido del nombre del archivo también cambia. Lo que a su vez cambia el hash del "árbol de directorios".
Cuando una base de datos git almacena un árbol de directorios, ese árbol de directorios implica e incluye todo el contenido de todos los subdirectorios y todos los archivos que contiene .
Está organizado en una estructura de árbol con punteros (inmutables, reutilizables) a blobs u otros árboles, pero lógicamente es una instantánea única del contenido completo de todo el árbol. La representación en la base de datos git no es el contenido de datos planos, pero lógicamente son todos sus datos y nada más.
Si serializa el árbol en un sistema de archivos, elimina todas las carpetas .git y le dice a git que agregue el árbol nuevamente a su base de datos, terminaría sin agregar nada a la base de datos: el elemento ya estaría allí.
Puede ser útil pensar en los hashes de git como un puntero contado de referencia a datos inmutables.
Si creó una aplicación en torno a eso, un documento es un grupo de páginas, que tienen capas, que tienen grupos, que tienen objetos.
Cuando desee cambiar un objeto, debe crear un grupo completamente nuevo para él. Si desea cambiar un grupo, debe crear una nueva capa, que necesita una nueva página, que necesita un nuevo documento.
Cada vez que cambia un solo objeto, genera un nuevo documento. El documento antiguo sigue existiendo. El documento nuevo y el antiguo comparten la mayor parte de su contenido: tienen las mismas páginas (excepto 1). Esa página tiene las mismas capas (excepto 1). Esa capa tiene los mismos grupos (excepto 1). Ese grupo tiene los mismos objetos (excepto 1).
Y por lo mismo, me refiero lógicamente a una copia, pero en términos de implementación es solo otro puntero contado de referencia al mismo objeto inmutable.
Un repositorio git se parece mucho a eso.
Esto significa que un conjunto de cambios git dado contiene su mensaje de confirmación (como un código hash), contiene su árbol de trabajo y contiene sus cambios principales.
Esos cambios principales contienen sus cambios principales, todo el camino de regreso.
La parte del repositorio de git que contiene la historia es esa cadena de cambios. Esa cadena de cambios lo hace en un nivel superior al árbol de "directorio": desde un árbol de "directorio", no se puede acceder de forma exclusiva a un conjunto de cambios y a la cadena de cambios.
Para averiguar qué le sucede a un archivo, comience con ese archivo en un conjunto de cambios. Ese conjunto de cambios tiene una historia. A menudo en ese historial, existe el mismo archivo con nombre, a veces con el mismo contenido. Si el contenido es el mismo, no hubo cambios en el archivo. Si es diferente, hay un cambio y se debe trabajar para determinar exactamente qué.
A veces el archivo se ha ido; pero, el árbol de "directorio" podría tener otro archivo con el mismo contenido (mismo código hash), por lo que podemos rastrearlo de esa manera (nota; es por eso que desea un commit-to-move un archivo separado de un commit-to -editar). O el mismo nombre de archivo, y después de verificar el archivo es lo suficientemente similar.
Entonces git puede juntar un "historial de archivos".
Pero este historial de archivos proviene del análisis eficiente del "conjunto de cambios completo", no de un enlace de una versión del archivo a otra.