Git Submodules
Los submódulos permiten incluir un repositorio dentro de otro como subdirectorio, manteniendo historiales separados.
Agregar submódulos
# Add a submodule
git submodule add https://github.com/user/lib.git libs/lib
# Add at specific branch
git submodule add -b main https://github.com/user/lib.git libs/lib
# Initialize after clone
git clone --recurse-submodules https://github.com/user/repo.git
# Or initialize separately
git clone https://github.com/user/repo.git
git submodule init
git submodule update
Trabajar con submódulos
# Update all submodules
git submodule update --remote
# Update specific submodule
git submodule update --remote libs/lib
# Fetch and merge submodule changes
cd libs/lib
git fetch
git merge origin/main
cd ../..
git add libs/lib
git commit -m "Update lib submodule"
# Pull with submodules
git pull --recurse-submodules
Configuración de submódulos
# .gitmodules file
[submodule "libs/lib"]
path = libs/lib
url = https://github.com/user/lib.git
branch = main
# Configure to always update
git config --global submodule.recurse true
# Set submodule to track branch
git config -f .gitmodules submodule.libs/lib.branch main
Eliminar submódulos
# Remove submodule
git submodule deinit libs/lib
git rm libs/lib
rm -rf .git/modules/libs/lib
git commit -m "Remove lib submodule"
Estado de submódulos
# Check submodule status
git submodule status
# Show submodule summary
git submodule summary
# Show submodule diff
git diff --submodule
Git Subtrees
Los subtrees integran otro repositorio dentro de un subdirectorio, manteniendo todo el historial en un solo repo.
Agregar subtrees
# Add a subtree
git subtree add --prefix=libs/lib https://github.com/user/lib.git main --squash
# Without squash (keeps full history)
git subtree add --prefix=libs/lib https://github.com/user/lib.git main
Actualizar subtrees
# Pull updates from subtree remote
git subtree pull --prefix=libs/lib https://github.com/user/lib.git main --squash
# Add remote for convenience
git remote add lib https://github.com/user/lib.git
# Then pull
git subtree pull --prefix=libs/lib lib main --squash
Contribuir de vuelta al subtree
# Push changes back to subtree repository
git subtree push --prefix=libs/lib lib main
# Or create a branch
git subtree split --prefix=libs/lib -b lib-changes
git push lib lib-changes:main
Estrategia de merge para subtree
# Alternative: Use merge strategy
git remote add lib https://github.com/user/lib.git
git fetch lib
git merge -s subtree --allow-unrelated-histories lib/main
Submodules vs Subtrees
| Submodules | Subtrees |
|---|---|
| Repositorios separados | Repositorio único |
| Requiere comandos extra | Funciona con Git estándar |
| Apunta a commit específico | Fusiona historial completo |
| Tamaño menor del repo | Tamaño mayor del repo |
| Dependencia más explícita | Más simple para colaboradores |
Cuándo usar cada uno
Usa Submodules cuando:
- La dependencia se desarrolla de forma independiente
- Necesitas fijar versiones específicas
- El tamaño del repo importa
- El equipo se siente cómodo con submodules
Usa Subtrees cuando:
- Quieres un flujo más simple
- Los colaboradores no deben saber de dependencias
- Estás vendorizando una librería
- Rara vez necesitas actualizar la dependencia
Ejemplo práctico: monorepo con subtrees
# Create monorepo structure
mkdir monorepo && cd monorepo
git init
# Add existing projects as subtrees
git subtree add --prefix=packages/frontend ../frontend main
git subtree add --prefix=packages/backend ../backend main
git subtree add --prefix=packages/shared ../shared main
# Structure:
# monorepo/
# ├── packages/
# │ ├── frontend/
# │ ├── backend/
# │ └── shared/
# └── .git/