en Git

Cómo utilizar los submodulos git

submodules

Los submodulos git son una manera de linkar un repositorio dentro de otro. Por ejemplo, si tu proyecto necesita utilizar un proyecto que está en Github, puedes utilizar un submodulo para enlazar este repositorio en vez de copiar y pegar todo el código dentro de tu proyecto

Para pixelovers por ejemplo, me interesa tener el proyecto WordPress montado como submodulo, asi tengo desacoplados los plugins, los themes y toda la parte «custom» de lo que es el «core» de wordpress. Esto me permite actualizar la version de WordPress sin problemas y en mi repositorio tengo solo aquellos archivos que realmente son exclusivos de mi proyecto.

En este post vamos a explicar como:

  • Cómo añadir un submodulo a tu proyecto
  • Cómo clonar repositorios con submodulos
  • Cómo actualizar submodulos git
  • Cómo clonar repositorios con submodulos git que a su vez contienen otros submodulos git
  • Cómo eliminar submodulos git

Preparando el terreno

Desde tu cuenta de Github (si no tienes una ¡a qué esperas!) te tienes que crear un repositorio. Os recomiendo que os hagais un fork de uno que os tengo ya preparado para la ocasion: https://github.com/pixelovers/working-with-submodules.git

Captura de pantalla 2015-04-28 a las 19.51.05

Asi una vez hecho el fork ya podeis trabajar desde vuestro repositorio y modificar (y hacer push lo que querais)

Despues del fork sustituye #USERNAME# por tu usuario de GitHub

git clone https://github.com/#USERNAME#/working-with-submodules.git  project-with-submodules

Añadiendo un submodulo

En este proyecto recien creado (project-with-submodules) quiero añadir el codigo de otro repositorio llamado atomic-css-sass que contiene serie de clases ya definidas. Como atomic-css-sass es un proyecto que evoluciona por su lado me interesa añadirlo como submodulo al mio

Para ello utilizo git submodule add de la siguiente manera

$ cd project-with-submodules
$ git submodule add https://github.com/pixelovers/atomics-css-sass.git some-css
Cloning into 'some-css'...
remote: Counting objects: 25, done.
remote: Total 25 (delta 0), reused 0 (delta 0), pack-reused 25
Unpacking objects: 100% (25/25), done.
Checking connectivity... done.

Con esto registramos atomics-css-sass como submodulo de nuestro proyecto y clonamos los datos dentro del directorio some-css

El comando git submodule status nos dirá que el submodulo ha sido registrado y a qué commit está apuntando en la carpeta some-css

$ git submodule status
 b53e87efc273b69a8c913bc345557ef93afad79e some-css (heads/master)

Ademas, para ver los cambios que han sido registrados en el repositorio padre (project-with-submodules) podemos

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
    new file:   .gitmodules
    new file:   some-css

Esto nos indica que 2 archivos han sido modificados:

  • .gitmodules que contiene informacion sobre el repositorio del submodulo
  • some-css que es el propio submodulo

Git no trackea los archivos dentro del submodulo. Cuando estas en el repositorio padre ve el submodulo como un archivo.

Antes de continuar hacemos commit de nuestros cambios y hacemos push a nuestro repositorio remoto

$ git commit -m 'Added some-css submodule'
[master 7bcc9a8] Added some-css submodule
 2 files changed, 4 insertions(+)
 create mode 100644 .gitmodules
 create mode 160000 some-css

$ git push
Counting objects: 4, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 448 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To https://github.com/pixelovers/working-with-submodules.git
   8f5f607..7bcc9a8  master -> master

Una vez hecho esto, podemos fijarnos en nuestro repositorio remoto (Github) donde veremos un link al repositorio atomics-css-sass con el nombre some_css

Captura de pantalla 2015-04-28 a las 20.16.53

Clonando un repositorio con submodulos

Vamos a clonar el repositorio con el que estamos trabajando en una carpeta diferente

Para ello hacemos (sustituye #USERNAME# por tu usuario de GitHub)

git clone https://github.com/#USERNAME#/working-with-submodules.git project-cloned-with-submodules

 

Una vez clonado el proyecto, si nos vamos a la carpeta project-cloned-with-submodules veremos que está vacia.

$ cd project-cloned-with-submodules/some-css/
$ ls -la
total 0

¿Que ha pasado? NOooooooo. Interneeeeeeerrrr 🙂

Por defecto git clone no hace pull de los submodulos git a la vez que el repositorioi padre. Para «bajar» el codigo tendremos que:

  • registrar el submodulo con git submodule init
  • hacer pull del codigo del submodulo con git submodule update
$ cd project-cloned-with-submodules/

$ git submodule init
Submodule 'some-css' (https://github.com/pixelovers/atomics-css-sass.git) registered for path 'some-css'

$ git submodule update
Cloning into 'some-css'...
remote: Counting objects: 25, done.
remote: Total 25 (delta 0), reused 0 (delta 0), pack-reused 25
Unpacking objects: 100% (25/25), done.
Checking connectivity... done.
Submodule path 'some-css': checked out 'b53e87efc273b69a8c913bc345557ef93afad79e

Actualizando un submodulo

Los submodulos son simplemente repositorios de git dentro de otros. Por tanto dentro del submodulo puedes utilizar todas las acciones git como push, pull, status, etc… Asi que si quieres asegurarte de que tu submodulo está actualizado a la última version de tu repositorio remoto pues hacer simplemente git pull

$ git pull
You are not currently on a branch. Please specify which
branch you want to merge with. See git-pull(1) for details.
    git pull <remote> <branch>

Si obtenemos este error podemos hacer

$ git checkout master
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.

Y a partir de ahi ya funcionará bien

$ git pull
Already up-to-date.

Si nuestro submodulo se baja algunos cambios al hacer el pull entonces el repositorio padre nos dirá que hay cambios pendientes de comitear. El submodulo apunta a un commit concreto, y si ese commit cambia el repositorio padre registra el cambio.

Si necesitamos que el submodulo esté en un commit concreto podemos utilizar git reset

$ git reset --hard b53e87
HEAD is now at b53e87e intructions README.md

Una vez hecho podemos ir al repositorio padre y registrar este cambio

cd ..
git commit -am 'Set submodule point to commit b53e87'

Cuando hagamos push de estos cambios al repositorio remoto el submodulo quedará asociado a este commit en particular.

Submodulos git que contienen otros submodulos git

Otra gran característica de los submodulos git es que pueden a su vez contener otro submodulos git

Por ejemplo, el repositorio atomic-css-sass contiene a su vez otro submodulo en la ruta /src/scss/helpers

En este punto, en hemos actualizado el repostorio atomic-css-sass en la carpeta some_css pero ninguno de sus submodulos han sido pulled

Si vamos al directorio some_css y hacemos git submodule status

$ git submodule status
-5f76d83120eb49c2147a0f8ad930aff79c97e17d src/scss/helpers

Vemos que hay un submodulo para el repositorio atomic-css-sass. El signo - al principio de cada linea nos indica que el submodulo no ha sido descargado aun. Podriamos hacer git init y git update lo que clonaria todos los repositorios y los colocaria en su correspondiente lugar.

¿Pero tengo que hacer esto siempre que clone un repositorio con submodulos? ¿Que pasa si estos submodulos tienen a su vez submodulos? ¿Tengo que ir carpeta por carpeta con submodulo haciendo init y update?

Pues no 🙂

Podemos decirle a git que cuando clone un repositorio (git clone) con submodulos, automaticamente actualize todos los que encuentre (--recursive)

En nuestro ejemplo, si clonamos en otra carpeta seria

git clone --recursive https://github.com/#USERNAME#/working-with-submodules.git project-cloned-with-submodules-well-done

No olvides de sustituir #USERNAME# por tu nombre de usuario

Eliminado submodulos git

Podemos decidir tambien que no queremos utilizar mas el submodulo porque hemos encontrado una manera mejor de manejar la dependencia o porque hay problemas con el submodulo y quieres borrarlo y empezar de nuevo.

Pero esto no es tan facil como hacer

git rm -rf some_css

Si hacemos esto asi, git se quejará.

Para eliminar el modulo tenemos que:

1.- Eliminar las referencias al modulo en el archivo .gitmodules que está en la raiz del proyecto (si solo tenemos un submodulo podemos eliminar directamente este archivo)

  [submodule "some-css"]
    path = some-css
    url = https://github.com/pixelovers/atomics-css-sass.git

Pero esto no es suficiente, hay un sitio más donde queda definido el submodulo.

$ git submodule status
No submodule mapping found in .gitmodules for path 'some-css'

Los submodulos git tambien quedan registrados en el archivos .git/config

[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
        ignorecase = true
        precomposeunicode = true
[remote "origin"]
        url = https://github.com/pixelovers/working-with-submodules.git
        fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
        remote = origin
        merge = refs/heads/master
[submodule "some-css"]
        url = https://github.com/pixelovers/atomics-css-sass.git

2.- Asi que tambien tenemos que eliminar las lineas que referencian al submodulo que encontramos al final del archivo

3.- Y por ultimo, tenemos que eliminar la cache git del submodulo

$ git rm --cached some-css
rm 'some-css'

Con esto ya tenemos el submodulo, completamente eliminado y ya podemos hacer commit y push para registrar los cambios

$ git commit -m "submodule removed"
[master 61b4f31] submodule removed
 1 file changed, 1 deletion(-)
 delete mode 160000 some-css

$ git push

Enlaces y mas

Post Anterior
Post Siguiente

Política de Comentarios de pixelovers

Responsable » Juan Manuel Garrido
Finalidad » Moderación de los comentarios
Legitimación » Tu consentimiento expreso que te será requerido por Disqus.
Destinatarios » Los datos de tus comentarios los guardará Disqus, mi sistema de comentarios, que está acogido al acuerdo de seguridad EU-US Privacy Shield tal y como recoge su politica de privacidad
Derechos » Desde Disqus, por tanto, podrás acceder, rectificar, limitar y suprimir tus comentarios o tu cuenta
Tienes más detalles acerca del tratamiento de los datos relacionados con los comentarios en nuestra (Política de Privacidad)