git subtree: la alternativa al submódulo de Git
Nicola Paolucci
Experto en desarrollo
Internet está lleno de artículos sobre por qué no debes usar submódulos de Git. Aunque los submódulos vienen muy bien en algunos casos, tienen varios inconvenientes.
Por supuesto, hay alternativas. Existen (al menos) dos herramientas con las que rastrear el historial de dependencias de software de tu proyecto y, al mismo tiempo, poder seguir usando Git:
Subárbol de Git
- Repositorio de Google
En esta entrada, voy a analizar git subtree
y mostraré por qué es una mejora (aunque no sea perfecta) respecto al submódulo de Git.
¿Qué es git subtree y cuáles son sus ventajas?
Con git subtree
puedes anidar un repositorio dentro de otro en forma de subdirectorio. Es una de las formas en que los proyectos de Git pueden gestionar las dependencias de los proyectos.
Ventajas de git subtree
:
- Gestionar un flujo de trabajo sencillo es fácil.
- Se admiten versiones anteriores de Git (incluso anteriores a la v1.5.2).
- El código del subproyecto está disponible nada más clonar el superproyecto.
- Para usar
git subtree
, los usuarios de tu repositorio no tienen que aprender nada nuevo. Ni siquiera necesitan saber que estás usandogit subtree
para gestionar las dependencias. git subtree
no añade nuevos archivos de metadatos como lo hace el submódulo de Git (.gitmodule).- El contenido del módulo se puede modificar sin tener una copia de repositorio independiente de la dependencia en otro lugar.
Inconvenientes (en nuestra opinión, bastante aceptables):
- Debes aprender una nueva estrategia de fusión (
git subtree
). - Aportar código para subproyectos de nivel superior es algo más complicado.
- Tienes la responsabilidad de no mezclar código de superproyecto y subproyecto en las confirmaciones.
Material relacionado
Cómo mover un repositorio de Git completo
VER LA SOLUCIÓN
Aprende a usar Git con Bitbucket Cloud
Cómo usar git subtree
git subtree
está disponible en la versión estándar de Git desde mayo de 2012 (v1.7.11 y posteriores). En la versión instalada por Homebrew en OS X, subtree está integrado correctamente, pero puede que en otras plataformas tengas que seguir las instrucciones de instalación.
Aquí puedes ver un ejemplo canónico de rastrear un plugin de Vim con git subtree
.
La vía rápida sin seguimiento remoto
Si solo quieres cortar y pegar un par de líneas, lee este párrafo. En primer lugar, añade subtree
en una carpeta prefix determinada:
git subtree add --prefix .vim/bundle/tpope-vim-surround https://bitbucket.org/vim-plugins-mirror/vim-surround.git main --squash
Lo habitual es no almacenar todo el historial del subproyecto en tu repositorio principal, pero si quieres conservarlo omite la marca --squash.
El comando anterior da este resultado:
git fetch https://bitbucket.org/vim-plugins-mirror/vim-surround.git main
warning: no common commits
remote: Counting objects: 338, done.
remote: Compressing objects: 100% (145/145), done.
remote: Total 338 (delta 101), reused 323 (delta 89)
Receiving objects: 100% (338/338), 71.46 KiB, done.
Resolving deltas: 100% (101/101), done.
From https://bitbucket.org/vim-plugins-mirror/vim-surround.git
* branch main -} FETCH_HEAD
Added dir '.vim/bundle/tpope-vim-surround'
Como puedes ver, esto registra una merge commit combinando con squash todo el historial del repositorio vim-surround en uno solo:
1bda0bd [3 minutes ago] (HEAD, stree) Merge commit 'ca1f4da9f0b93346bba9a430c889a95f75dc0a83' as '.vim/bundle/tpope-vim-surround' [Nicola Paolucci]
ca1f4da [3 minutes ago] Squashed '.vim/bundle/tpope-vim-surround/' content from commit 02199ea [Nicola Paolucci]
Si después de un tiempo quieres actualizar el código del plugin desde el repositorio de nivel superior, puedes hacer un git subtree pull
:
git subtree pull --prefix .vim/bundle/tpope-vim-surround https://bitbucket.org/vim-plugins-mirror/vim-surround.git main --squash
Es algo rápido e indoloro, pero los comandos son un poco largos y difíciles de recordar. Para acortar los comandos, podemos añadir el subproyecto como remoto.
Añadir el subproyecto como remoto
Si agregamos el subtree como remoto, podemos acortar las referencias:
git remote add -f tpope-vim-surround https://bitbucket.org/vim-plugins-mirror/vim-surround.git
Ahora podemos añadir el subtree (como antes), pero con una referencia más corta al remoto:
git subtree add --prefix .vim/bundle/tpope-vim-surround tpope-vim-surround main --squash
El comando para actualizar el subproyecto en una fecha posterior pasa a ser:
git fetch tpope-vim-surround main
git subtree pull --prefix .vim/bundle/tpope-vim-surround tpope-vim-surround main --squash
Aportar código a nivel superior
Ahora podemos confirmar las correcciones que queremos en el subproyecto de nuestro directorio de trabajo local. Cuando llegue el momento de aportar código al proyecto de nivel superior, habrá que bifurcar el proyecto y añadirlo como otro remoto:
git remote add durdn-vim-surround ssh://git@bitbucket.org/durdn/vim-surround.git
Ahora podemos usar el comando subtree push de la siguiente manera:
git subtree push --prefix=.vim/bundle/tpope-vim-surround/ durdn-vim-surround main
git push using: durdn-vim-surround main
Counting objects: 5, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 308 bytes, done.
Total 3 (delta 2), reused 0 (delta 0)
To ssh://git@bitbucket.org/durdn/vim-surround.git
02199ea..dcacd4b dcacd4b21fe51c9b5824370b3b224c440b3470cb -} main
Con esto, estamos listos y podemos abrir una solicitud de incorporación de cambios para el mantenedor del paquete.
¿Se puede hacer sin el comando git subtree?
¡Sí! Sí se puede. git subtree
es diferente de la estrategia de fusión de subárboles. Puedes seguir usando la estrategia de fusión, aunque, por alguna razón, git subtree
no esté disponible. Sigue estos pasos.
Añade la dependencia como git remote
:
git remote add -f tpope-vim-surround https://bitbucket.org/vim-plugins-mirror/vim-surround.git
Antes de leer el contenido de la dependencia en el repositorio, es importante registrar una fusión para poder rastrear todo el historial del árbol del plugin hasta el momento:
git merge -s ours --no-commit tpope-vim-surround/main
Esta es la salida:
Automatic merge went well; stopped before committing as requested
Después, leemos el contenido del último objeto árbol en el repositorio de plugin en nuestro directorio de trabajo listo para la confirmación:
git read-tree --prefix=.vim/bundle/tpope-vim-surround/ -u tpope-vim-surround/main
Ahora podemos confirmar (y será una confirmación de fusión que preservará el historial del árbol que leemos):
git ci -m"[subtree] adding tpope-vim-surround"
[stree 779b094] [subtree] adding tpope-vim-surround
Si queremos actualizar el proyecto, ahora podemos hacer una incorporación con la estrategia de fusión de git subtree
:
git pull -s subtree tpope-vim-surround main
El comando git subtree es una gran alternativa
Después de llevar un tiempo usando submódulos de Git, verás que git subtree
resuelve muchos de los problemas con los submódulos. Como de costumbre, con todo lo relacionado con Git, hay una curva de aprendizaje para sacar todo el partido de la función.
Para seguir aprendiendo sobre Git, sígueme en Twitter (@durdn). Recuerda también echar un vistazo a Bitbucket de Atlassian si buscas una buena herramienta para gestionar tus repositorios de Git.
Actualización: Después de publicar este artículo, escribí otro artículo sobre la eficacia de git subtree.
Compartir este artículo
Tema siguiente
Lecturas recomendadas
Consulta estos recursos para conocer los tipos de equipos de DevOps o para estar al tanto de las novedades sobre DevOps en Atlassian.