A menudo sucede que mientras se trabaja en un proyecto, es necesario utilizar otro proyecto desde su interior. Tal vez es una biblioteca que un tercer desarrollador está desarrollando por separado o tal vez por el uso de múltiples proyectos bien delimitados. Ocurre que tenemos un problema común que surge en estos escenarios: quieres ser capaz de tratar los dos proyectos por separado y aun así ser capaz de utilizar uno dentro del otro.
Git tiene una solucion a este problema utilizando submódulos. Los submódulos te permiten mantener un repositorio Git como un subdirectorio de otro repositorio. Esto permite clonar otro repositorio en tu proyecto y mantener sus codigos separados.
Añadir submódulo
Añadir un submódulo a un repositorios es tan sencillo como:
1 |
git submodule add https://github.com/chaconinc/DbConnector |
O sea, agregamos un repositorio a nuestro repositorio. Esta acción creara el fichero .gitmodules.
El submódulo se añadirá en una carpeta con el mismo nombre que se llama el repositorio agregado en la carpeta en la que estemos situados con la consola (por supuesto todo es configurable con parámetros)
Clonar repositorio con submódulos
Clonar un repositorio es incluso más fácil. Tenemos varias formas:
1 2 3 |
git clone https://plainconcepts.visualstudio.com/DefaultCollection/_git/OurRepo git submodule init git submodule update |
Pero mejor en una sola línea. –recurse-submodules nos recorre todos los submódulos del fichero .gitmodules y nos clona repositorio y submódulos.
1 |
git clone --recurse-submodules https://plainconcepts.visualstudio.com/DefaultCollection/_git/OurRepo |
Existe un caso en el que –recurse-submodules, no es recomendable: Cuando tenemos un repositorio con dos ramas (develop y master) y la rama por defecto (master) no contiene todavía el fichero .gitmodules. En este caso Git clonara el repositorio, se posicionara en master y al no tener el fichero .gitmodules no descargara ningún submódulo. Por lo que en este caso lo recomendable es hacer un git submodule update.
Trabajando con submódulos
Tenemos tres casos de navegación.
Si iniciamos una consola en la carpeta donde tenemos el repositorio del submódulo. Esto es, donde hemos clonado el repositorio donde está el código que hemos agregado a nuestro proyecto principal como submódulo. Evidentemente estamos en el repositorio del submódulo y podemos agregar cambios a nuestro submodulo.
Pero si abrimos la consola en la carpeta de nuestro proyecto principal nos encontraremos con que no podemos acceder a los cambios que hay en un submódulo. Pero si hacemos un git status, al menos nos indicara que hay cambios en el submódulo.
1 2 3 4 5 6 7 8 9 |
$ git status On branch master Your branch is up-to-date with 'origin/master'. Changes not staged for commit: modified: Submodules/MySubmodule (new commits, modified content) no changes added to commit (use "git add" and/or "git commit -a") |
Si usamos diff para ver qué hay de nuevo en nuestro submódulo (por ejemplo, una nueva feature que se haya incorporado en algún commit nuevo). Lo único que nos muestra es que el puntero de nuestra copia no es el mismo que el puntero actual del submódulo.
1 2 3 4 5 6 7 8 9 10 11 12 |
$ git diff diff --git a/src/Submodules/MagusChart b/src/Submodules/MagusChart index 424774d..8be562a 160000 --- a/src/Submodules/MySubmodule +++ b/src/Submodules/MySubmodule @@ -1 +1 @@ -Subproject commit 424774da2a3b1e08b6d7b6de90b367f96a3b8b1e +Subproject commit 8be562a424582ba459d9285cb0ce8945b120ea95-dirty |
Entonces, ¿que debemos usar? Desde el repositorio principal podemos usar git diff –submodule para ver qué cambios específicos hay (nuevos commits). Esto nos interesa a la hora de saber si el submodulo se ha actualizado y debemos traer nuevos cambios.
1 2 3 4 5 6 |
$ git diff --submodule Submodule src/Submodules/MySubmodule contains modified content Submodule src/Submodules/MySubmodule 424774d..8be562a: > Updated the library for tests |
Actualizando nuestros submódulos
Esto es, cuando nos actualizan el repositorio de nuestro submódulo y queremos traer el nuevo código desde el repositorio principal.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
$ git submodule update $ git status On branch master Your branch is up-to-date with 'origin/master'. modified: src/Submodules/MySubmodule (new commits) $ git submodule update Submodule path 'src/Submodules/MySubmodule': checked out '424774da2a3b1e08b6d7b6de90b367f96a3b8b1e' $ git status On branch master Your branch is up-to-date with 'origin/master'. |
Si navegamos hasta nuestro submódulo y entramos en el contexto del repositorio del submódulo, vemos que no está posicionando en master, se ha generado el nuevo commit pero no se ha movido HEAD.
1 2 3 4 5 6 7 8 9 |
$ cd MagusChart/~/Desktop/MagusDesktop/src/Submodules/MySubmodule((424774d...)) $ git checkout master Previous HEAD position was 424774d... Include initial structure Switched to branch 'master' Your branch is up-to-date with 'origin/master'. |
Ahora el repositorio submódulo ya está actualizado y en el commit actual.
Cuidado: con git submodule update. Tarda un poco en darse cuenta que hay nuevos commit en remoto.
Kenny R.
3 mayo, 2017 a las 14:47
Buen artículo, a ver si lo consigo 🙂