Meta vs Git: por qué eligieron Mercurial para su monorepo

El otro día un desarrollador junior de mi equipo me preguntó: “¿Por qué usamos Git? ¿No hay nada mejor?”. Mi respuesta automática fue ese clásico “porque es el estándar”. Pero después recordé esta historia fascinante que desafía todo lo que damos por sentado en el desarrollo de software.
Mientras Git domina con un aplastante 93% del mercado según Stack Overflow, algunas de las mentes más brillantes de la industria decidieron ir completamente a contracorriente. Meta apostó por Mercurial, un sistema que muchos consideraban anticuado o en vías de extinción, para gestionar posiblemente el repositorio de código más monstruoso y activo del planeta.
Y aquí viene lo interesante: no fue por capricho ni por ser diferentes. Esta decisión, que parece ir totalmente contra la corriente del consenso técnico en la era de Git, revela lecciones brutalmente honestas sobre ingeniería a escala extrema.
La bestia indomable: El monorepo que desafía toda lógica
Para entender esta decisión, primero hay que dimensionar el problema:
¿Qué estamos midiendo? | Tamaño en Meta | Para que te hagas una idea... |
---|---|---|
Tamaño del repositorio | Más de 100GB | Como 54 kernels de Linux juntos |
Commits diarios | ~1,000 | Un commit cada minuto y medio, sin descanso |
Desarrolladores activos | Más de 15,000 | La población de una pequeña ciudad como Valdivia en Chile |
Archivos en el repositorio | Millones | Como todos los documentos de una gran biblioteca nacional |
Meta utiliza un enfoque de monorepo para casi todo su código, lo que significa que Facebook, Instagram, WhatsApp, Messenger y sus herramientas internas viven en un solo repositorio gigante. Esta estrategia tiene grandes ventajas para la colaboración y la integración continua, pero plantea desafíos enormes para cualquier sistema de control de versiones.
Cuando Git alcanzó sus límites
1. Problemas de rendimiento con repositorios gigantes
# Example: Cloning a large Git repository can be prohibitively slow
$ time git clone https://example.com/massive-repo.git
# Output: real 45m22.243s
# The same repository with Mercurial (optimized)
$ time hg clone https://example.com/massive-repo
# Output: real 12m33.541s
Git fue creado por Linus Torvalds para gestionar el kernel de Linux, y es una maravilla para lo que fue diseñado. Pero tiene sus límites cuando los repositorios crecen demasiado:
- Operaciones cada vez más lentas: Comandos como
git status
,git log
y especialmentegit blame
se vuelven extremadamente lentos en repositorios masivos. - Problemas con la historia profunda: Git debe recorrer toda la historia de un archivo para muchas operaciones, lo que se vuelve insostenible con historiales extensos.
- Sobrecarga de indexación: El índice de Git (.git/index) se convierte en un cuello de botella para repositorios con millones de archivos.
“Git simplemente no escala para el tamaño de nuestro repositorio. Hemos optimizado Mercurial para manejar nuestro monorepo de una manera que no habría sido posible con Git sin reescribirlo casi por completo.” — Ingeniero de Infraestructura de Meta
2. Manejo ineficiente de archivos binarios y grandes
Meta maneja una cantidad significativa de archivos binarios: imágenes, videos, modelos ML, compilados, etc. Git almacena cada versión completa de estos archivos, lo que rápidamente infla el tamaño del repositorio y ralentiza las operaciones.
Mercurial proporcionaba una mejor base para implementar extensiones como Largefiles que almacenan binarios grandes fuera del historial principal.
3. Una arquitectura más adaptable para personalización
La arquitectura de Mercurial resultó ser fundamentalmente más adaptable a las necesidades extremas de Meta:
# Simplified example of a custom Mercurial extension at Meta
# that optimizes commit performance for massive repositories
@command('commitoptimized', [], 'hg commitoptimized [OPTIONS] [FILE]')
def commit_optimized(ui, repo, *pats, **opts):
"""Commit with optimizations for massive repositories"""
# Custom implementation for handling large changesets
with repo.lock(), repo.transaction("commit"):
# Custom logic for handling millions of files
# and Meta-specific optimizations
pass
Mientras que Git está principalmente escrito en C con una arquitectura bastante monolítica, Mercurial:
- Está escrito principalmente en Python con partes críticas de rendimiento en C
- Ofrece un sistema de extensiones flexible y bien documentado
- Permite modificaciones profundas a través de “hooks” en casi cualquier parte del sistema
Esta flexibilidad permitió a Meta transformar Mercurial sin tener que reescribirlo completamente.
Cómo Meta convirtió Mercurial en una bestia de carga
Meta no simplemente adoptó Mercurial tal como es, sino que lo transformó radicalmente. Este proceso incluyó:
1. Desarrollo de Remora: Un sistema de almacenamiento personalizado
┌───────────────────┐ ┌───────────────────┐
│ │ │ │
│ Mercurial │ │ Remora │
│ Interface │────►│ Storage │
│ │ │ │
└───────────────────┘ └───────────────────┘
│
▼
┌───────────────────┐
│ │
│ Massive Scale │
│ Optimizations │
│ │
└───────────────────┘
Meta desarrolló Remora, un backend de almacenamiento personalizado que:
- Implementa almacenamiento distribuido para compartir la carga entre múltiples servidores
- Utiliza técnicas avanzadas de compresión y deduplicación para reducir drásticamente el espacio
- Introduce caching inteligente para acelerar las operaciones más comunes
2. Creación de Watchman para monitoreo de archivos
Para resolver problemas de rendimiento con operaciones como status
que necesitan identificar cambios en miles de archivos, Meta desarrolló Watchman:
- Servicio que monitorea continuamente el sistema de archivos para detectar cambios
- Proporciona información casi instantánea sobre archivos modificados
- Se integra con Mercurial para acelerar dramáticamente operaciones comunes
3. Sapling: El cliente de control de versiones de siguiente generación
Eventualmente, Meta evolucionó su trabajo en un nuevo cliente de control de versiones llamado Sapling (ahora de código abierto), que:
- Mantiene compatibilidad con repositorios Mercurial
- Está reescrito significativamente en Rust para un mayor rendimiento
- Incorpora lecciones aprendidas de años de optimizar el flujo de trabajo de desarrollo
Los beneficios tangibles de esta decisión audaz
La elección de Mercurial ha proporcionado beneficios medibles para el flujo de trabajo de desarrollo en Meta:
1. Eficiencia de desarrollo mejorada
- Clonado parcial: Los desarrolladores pueden clonar solo las partes del monorepo relevantes para su trabajo
- Tiempos de commit reducidos: El tiempo para completar commits ha pasado de minutos a segundos
- Mejor gestión de dependencias: Al estar todo en un mismo repositorio, las dependencias se gestionan de forma más coherente
2. Ventajas para CI/CD y testing
La infraestructura de pruebas y despliegue de Meta puede ahora:
- Determinar precisamente qué pruebas ejecutar basándose en los archivos modificados
- Mantener una única versión “verdadera” del estado del código
- Implementar mecanismos de bisect automatizados para identificar regresiones rápidamente
3. Innovación acelerada
# Example of how Meta can implement a new feature in Mercurial quickly
# by adding a new extension
def extsetup(ui):
"""Register new command and custom hooks"""
# Register a new custom command
entry = extensions.wrapcommand(commands.table, 'commit', commit_wrapper)
# Add a hook for commit pre-processing
ui.setconfig('hooks', 'pre-commit.meta-checks', meta_custom_checks)
La capacidad de personalizar profundamente Mercurial ha permitido a Meta implementar rápidamente innovaciones como:
- Sistema de revisión de código integrado con el control de versiones
- Herramientas de análisis estático que operan durante las operaciones de commit
- Resolución avanzada de conflictos asistida por IA
Lecciones para todos: ¿Cuándo considerar alternativas a Git?
La experiencia de Meta nos deja valiosas enseñanzas sobre cuándo buscar otras opciones:
1. Señales de que Git puede no ser suficiente
- Tu repositorio supera varios GB y las operaciones básicas se vuelven lentas
- Tienes miles de desarrolladores trabajando simultáneamente
- Manejas gran cantidad de archivos binarios o muy grandes
- Necesitas personalización profunda del sistema de control de versiones
2. Estrategias para repositorios masivos
- Considerar un enfoque de múltiples repositorios vs. monorepo según tus necesidades específicas
- Invertir en herramientas de integración si usas múltiples repositorios
- Implementar sistemas de cache y optimización para repositorios grandes
- Evaluar sistemas alternativos (Mercurial, Plastic SCM, Perforce) para casos extremos
El futuro del control de versiones a escala masiva
El trabajo de Meta con Mercurial está influenciando la próxima generación de sistemas de control de versiones:
- Sapling y Watchman están disponibles como proyectos de código abierto
- Sus innovaciones están inspirando nuevas características en Git y otros sistemas
- La comunidad está prestando más atención a los desafíos del desarrollo a escala extrema
Más allá del estándar: elegir la herramienta adecuada
La decisión de Meta de utilizar Mercurial en lugar de Git no significa que uno sea inherentemente mejor que el otro. Ilustra un principio fundamental: las herramientas deben adaptarse a las necesidades específicas del contexto.
Para la gran mayoría de proyectos y empresas (especialmente en Latinoamérica donde los equipos suelen ser más pequeños), Git sigue siendo una excelente opción. Sin embargo, el caso de Meta demuestra que en la frontera del desarrollo a escala masiva, las soluciones convencionales a veces deben dar paso a enfoques más especializados.
Esta voluntad de cuestionar el estándar y adaptar herramientas fundamentales a necesidades únicas ha sido clave para que Meta mantenga un ritmo acelerado de innovación, a pesar de su enorme base de código y equipo de desarrollo.
¿Te gustó este artículo?
Suscríbete para recibir más contenido como este directamente en tu inbox.