16 puntos por GN⁺ 2026-01-29 | 1 comentarios | Compartir por WhatsApp
  • Para entender la estructura interna de un sistema de control de versiones, implementó directamente un sistema similar a Git
  • Usa hashes SHA-256 y compresión zstd en lugar de SHA-1 y zlib de Git, y organiza el repositorio con una estructura de directorios .tvc
  • Está escrito en Rust, e implementa paso a paso funciones de hash de archivos, compresión, commit y checkout
  • El objeto commit incluye el hash del árbol, el commit padre, el autor y el mensaje, y los archivos idénticos no se vuelven a guardar gracias a la deduplicación por hash
  • Permite experimentar directamente que Git es un almacén de archivos basado en direccionamiento por contenido, y destaca la importancia de los formatos de datos estructurados

Método de hashing y compresión

  • Git identifica todos los objetos con hashes SHA-1, pero en este proyecto se usa SHA-256
    • SHA-1 es antiguo y tiene debilidades de seguridad, pero en este proyecto solo se usa para identificar el contenido de archivos, así que la seguridad no era importante
  • En lugar de zlib de Git, adoptó la biblioteca de compresión zstd de Facebook
    • Consideró que zstd era más eficiente, y la compatibilidad con Git no era un objetivo
  • El nombre del proyecto es “tvc (Tony’s Version Control)”, y usa los archivos .tvc y .tvcignore como equivalentes de la estructura correspondiente en Git

Etapas de implementación

  • El proceso de implementación sigue el orden leer argumentos del comando → leer reglas de exclusión → mostrar la lista de archivos → hashear y comprimir → crear árbol y commit → gestionar HEAD → hacer checkout del commit
  • Está escrito en Rust, y el comando ls aplica las reglas de .tvcignore para recorrer recursivamente los archivos no ignorados y mostrar el hash SHA-256 de cada uno
  • Con la biblioteca zstd implementó de forma sencilla funciones de compresión y descompresión de archivos

Estructura del commit

  • El objeto commit incluye la siguiente información
    1. Tipo de objeto (“commit”)
    2. Estado del sistema de archivos en ese momento (hash del árbol)
    3. Commit anterior (HEAD)
    4. Autor (author)
    5. Mensaje del commit
  • A diferencia de Git, omite la distinción entre autor y committer, y no implementa funciones como merge o rebase
  • Al crear un commit, genera, hashea y comprime el objeto árbol, lo guarda en .tvc/objects/ y actualiza el archivo HEAD
  • Si un archivo idéntico tiene el mismo hash, no se vuelve a guardar, lo que permite evitar almacenamiento duplicado

Objetos árbol y checkout

  • La función generate_tree() recorre directorios, hashea, comprime y guarda cada archivo, y construye una cadena con el nombre del archivo y su hash
    • Los subdirectorios se procesan recursivamente para formar la estructura de árbol
  • Los objetos commit y árbol se parsean como estructuras (Commit, Tree) para poder manejarlos fácilmente en memoria
  • La función generate_fs() reconstruye el sistema de archivos con base en la estructura de árbol y realiza el checkout en la ruta especificada

Lecciones del proyecto

  • Permitió experimentar de primera mano que Git es un almacén de archivos basado en contenido direccionable (clave-valor)
  • La parte más difícil fue el parseo del formato de objetos, y la próxima vez planea usar un formato más claro como YAML o JSON
  • El código completo está publicado en el repositorio de GitHub (tonystr/t-version-control)

1 comentarios

 
GN⁺ 2026-01-29
Opiniones en Hacker News
  • Es interesante que Git sea el único SCM que soporta la estrategia de merge recursivo
    Este método recuerda automáticamente resoluciones de conflictos pasadas, así que es muy útil
    Mucha gente todavía prefiere rebase, pero al implementar merge, hay que incluir sí o sí un mecanismo para guardar el historial de resolución de conflictos
    Referencia relacionada: Merge made by recursive strategy

    • En un trabajo anterior, si no activabas la función rerere de git, no recordaba resoluciones de conflictos previas
      Referencia: Git Tools - Rerere
    • Hay un texto del autor de Mercurial sobre el merge recursivo
      Enlace
    • Me enteré hace poco de que git merge no tiene una estrategia “null”
      Incluso cuando ya resolviste los conflictos y solo quieres dejar registro del merge, Git intenta ayudarte de todos modos
      Ojalá existiera una opción para simplemente registrar el merge sin tocar el índice ni el working tree
    • Una forma más sólida de manejar conflictos es tratar el conflicto mismo como un objeto de primera clase del repositorio
      Por ejemplo, Pijul hace eso
    • Personalmente odio git squash
      No puedes ver los intentos de varios commits, es más difícil revertirlo y cuesta seguir trabajando sobre una rama que ya fue mergeada
      Cuando varios PR son piezas de un mismo rompecabezas, me parece mucho mejor hacer merge normal
  • Siempre es divertido aprender el funcionamiento interno de una herramienta que usas todos los días
    En especial, Git from the Bottom Up es un texto excelente que explica claramente la estructura interna de Git
    En unos 20 minutos puedes entender el mecanismo opaco detrás de los comandos de Git

    • Yo llegué a entender Git por completo gracias a The Git Parable
    • Qué gusto volver a encontrar un texto que me ayudó muchísimo cuando estaba aprendiendo Git
    • Recién ahora me entero de que con el comando cat-file puedes inspeccionar directamente IDs hash, y está bastante genial
  • Si te da curiosidad cómo planifican los agentes de código, este tipo de textos forma parte de sus datos de entrenamiento
    Aunque si el autor recibió ayuda de un LLM, entonces podría volverse una situación recursiva

    • Revisé GitHub Insights y, antes de publicar el texto, ya había 49 clones y 28 clonadores únicos
      Parece que sí existen bots que raspan repositorios públicos
      Es una sensación extraña pensar que mi código podría usarse para entrenar LLM
      El texto en sí no tiene salida de LLM, pero sí usé ChatGPT para consultar convenciones de código en Rust o consejos comparando algoritmos
    • También suena divertida la idea de contaminar los LLM con un bucle de blogs autorreferencial
    • Sería un problema si la salida del modelo volviera a entrar como dato de entrenamiento, pero si pasa por edición humana quizá pueda ser algo útil
    • Cuando Gemini a veces suena con un estilo de inglés con acento indio, da la impresión de que debe haber una enorme cantidad de datasets generados en India
    • Si escribes blogs con herramientas de IA, puede generarse este ciclo, así que hasta parece una buena razón para escribir sin IA
  • El tutorial CodeCrafters “Build your own Git” es realmente excelente
    También recomiendo el video en vivo de Jon Gjengset, donde lo implementa directamente en Rust

  • Yo también quisiera que el control de versiones se usara mucho más fuera del software
    GotVC es un proyecto interesante con cifrado E2E, importación paralela y una estructura compatible con archivos grandes

    • Más allá de archivos de texto, se vuelve difícil detectar la diferencia entre dos versiones
      Al final tienes que abrirlas en el programa original para compararlas
    • Me pregunto si saben que ya existe un proyecto llamado Game of Trees(Got)
  • Este texto me hizo pensar en ugit: DIY Git in Python
    Es uno de los mejores recursos para profundizar en el interior de Git sin dejar de ser fácil de seguir

    • El diseño de la página es tan bonito que la guardé en marcadores
    • En una línea parecida, también me divertí siguiendo Write yourself a Git
    • Yo traté de mapear operaciones de Git a un grafo de Neo4j, y me ayudó muchísimo a entender la estructura
  • Sapling VCS, el fork de Mercurial de Meta, usa compresión con diccionario Zstd
    En la documentación explicativa se puede comparar con el packfile comprimido por delta de Git
    En repositorios pequeños, la compresión delta de Git es más eficiente, pero en repositorios grandes es mejor la compresión con diccionario basada en rutas
    Hace poco Git también añadió una función similar llamada “path-walk”

  • Yo también hice un intento parecido, y mi proyecto se llama “shit
    Enlace de GitHub

    • El nombre “Fast Useful Change Keeper” tiene buen ingenio
    • De verdad es “THE shit”
  • Hace tiempo intenté hacer un framework SPA y recuerdo haberme sorprendido por la complejidad oculta
    Imagino que los desarrolladores de React o Angular también deben haber pasado por esa madriguera de conejo
    Git también oculta muy bien su complejidad

    • Solo cuando intentas implementar Git tú mismo entiendes de verdad lo que significa esa frase
  • Vi un cliente de Git escrito en PHP que puede leer packfile y reftable, y también soporta diff basado en LCS
    gipht-horse

    • Creo que este repositorio es una gran victoria (W) para PHP
      Y además hoy me enteré de que puedes usar @ en lugar de HEAD, lo cual sintácticamente tiene bastante sentido