321 votos

¿Cómo puedo especificar una rama/etiqueta al añadir un submódulo Git?

¿Cómo es que git submodule add -b ¿trabajo?

Después de añadir un submódulo con una rama específica, un nuevo repositorio clonado (después de git submodule update --init ) estará en un commit específico, no en la propia rama ( git status en el submódulo muestra "No está actualmente en ninguna rama").

No puedo encontrar ninguna información sobre .gitmodules o .git/config sobre la rama del submódulo o cualquier commit específico, así que ¿cómo lo averigua Git?

Además, ¿es posible especificar una etiqueta en lugar de una rama?

Estoy usando la versión 1.6.5.2.

357voto

djacobs7 Puntos 3131

Nota: Git 1.8.2 ha añadido la posibilidad de seguir las ramas. Vea algunas de las respuestas a continuación.


Es un poco confuso acostumbrarse a esto, pero los submódulos no están en una rama. Son, como dices, sólo un puntero a un commit concreto del repositorio del submódulo.

Esto significa que, cuando otra persona revisa su repositorio, o extrae su código, y hace git submodule update, el submódulo se revisa a ese particular commit.

Esto es genial para un submódulo que no cambia a menudo, porque entonces todos en el proyecto pueden tener el submódulo en el mismo commit.

Si quieres mover el submódulo a una etiqueta concreta:

cd submodule_directory
git checkout v1.0
cd ..
git add submodule_directory
git commit -m "moved submodule to v1.0"
git push

Entonces, otro desarrollador que quiera tener submodule_directory cambiado a esa etiqueta, hace lo siguiente

git pull
git submodule update --init

git pull cambia a qué commit apunta su directorio de submódulos. git submodule update realmente se fusiona en el nuevo código.

128voto

VonC Puntos 414372

(Git 2.22, segundo trimestre de 2019, ha introducido git submodule set-branch --branch aBranch -- <submodule_path> )

Tenga en cuenta que si tiene un existente submódulo que no es rastreando una rama todavía , entonces ( si tienes git 1.8.2+ ):

  • Asegúrese de que el repositorio principal sabe que su submódulo ahora sigue una rama:

      cd /path/to/your/parent/repo
      git config -f .gitmodules submodule.<path>.branch <branch>
  • Asegúrese de que su submódulo está realmente en el último de esa rama:

      cd path/to/your/submodule
      git checkout -b branch --track origin/branch
        # if the master branch already exist:
        git branch -u origin/master master

         (siendo "origen" el nombre del repo remoto upstream del que se ha clonado el submódulo.
         A git remote -v dentro de ese submódulo lo mostrará. Normalmente, es 'origin')

  • No olvides registrar el nuevo estado de tu submódulo en tu repo principal:

      cd /path/to/your/parent/repo
      git add path/to/your/submodule
      git commit -m "Make submodule tracking a branch"
  • La actualización posterior de ese submódulo tendrá que utilizar el --remote opción:

      # update your submodule
      # --remote will also fetch and ensure that
      # the latest commit from the branch is used
      git submodule update --remote
    
      # to avoid fetching use
      git submodule update --remote --no-fetch 

Tenga en cuenta que con Git 2.10+ (tercer trimestre de 2016), puedes utilizar ' . ' como nombre de rama:

El nombre de la sucursal se registra como submodule.<name>.branch en .gitmodules para update --remote .
Un valor especial de . se utiliza para indicar que el nombre de la rama en el submódulo debe ser el mismo que el de la rama actual en el repositorio actual .

Pero, como se ha comentado por LubosD

Avec git checkout si el nombre de la rama a seguir es " . ", ¡se acabará tu trabajo no comprometido!
Utilice git switch en su lugar.

Eso significa Git 2.23 (agosto de 2019) o más.

Ver " Confundido por git checkout "


Si quieres actualizar todos tus submódulos siguiendo una rama:

    git submodule update --recursive --remote

Tenga en cuenta que el resultado, para cada submódulo actualizado, será casi siempre será un HEAD desprendida , como Dan Cameron nota en su respuesta .

( Clintm notas en los comentarios que, si se ejecuta git submodule update --remote y el sha1 resultante es el mismo que el de la rama en la que se encuentra el submódulo, no hará nada y dejará el submódulo todavía "en esa rama" y no en estado de cabeza desprendida).

Para asegurar que la rama se compruebe realmente (y que no se modifique el SHA1 del entrada especial que representa el submódulo del repositorio principal), sugiere:

git submodule foreach -q --recursive 'branch="$(git config -f $toplevel/.gitmodules submodule.$name.branch)"; git switch $branch'

Cada submódulo seguirá haciendo referencia al mismo SHA1, pero si haces nuevos commits, podrás empujarlos porque serán referenciados por la rama que quieres que siga el submódulo.
Después de ese push dentro de un submódulo, no te olvides de volver al repo padre, añadir, commit y empujar el nuevo SHA1 para esos submódulos modificados.

Obsérvese el uso de $toplevel , recomendado en los comentarios por Alexander Pogrebnyak .
$toplevel se introdujo en git1.7.2 en mayo de 2010: commit f030c96 .

contiene la ruta absoluta del directorio de nivel superior (donde .gitmodules es).

dtmland añade en los comentarios :

El foreach script fallará al comprobar los submódulos que no siguen una rama.
Sin embargo, este comando le ofrece ambas cosas:

 git submodule foreach -q --recursive 'branch="$(git config -f $toplevel/.gitmodules submodule.$name.branch)"; [ "$branch" = "" ] && git checkout master || git switch $branch' –

El mismo comando pero más fácil de leer:

git submodule foreach -q --recursive \
    'branch="$(git config -f $toplevel/.gitmodules submodule.$name.branch)"; \
     [ "$branch" = "" ] && \
     git checkout master || git switch $branch' –

umläute refina dtmland con una versión simplificada en los comentarios :

git submodule foreach -q --recursive 'git switch $(git config -f $toplevel/.gitmodules submodule.$name.branch || echo master)'

varias líneas:

git submodule foreach -q --recursive \
  'git switch \
  $(git config -f $toplevel/.gitmodules submodule.$name.branch || echo master)'

Antes de Git 2.26 (primer trimestre de 2020), un fetch al que se le dice que recupere recursivamente las actualizaciones en los submódulos produce inevitablemente montones de salida, y resulta difícil detectar los mensajes de error.

El comando ha sido enseñado para enumerar los submódulos que tenían errores al final de la operación .

Ver commit 0222540 (16 ene 2020) de Emily Shaffer ( nasamuffin ) .
(Fusionado por Junio C Hamano -- gitster -- en commit b5c71cc , 05 Feb 2020)

fetch : destacar el fallo durante la obtención del submódulo

Firmado por: Emily Shaffer

En los casos en los que falla la obtención de un submódulo cuando hay muchos submódulos, el error de la única obtención del submódulo que falla queda enterrado bajo la actividad de los otros submódulos si más de una obtención retrocedió en fetch-by-oid .
Llamar a un fallo tarde para que el usuario sea consciente de que algo salió mal, y donde .

Porque fetch_finish() sólo es llamado de forma sincrónica por run_processes_parallel, no es necesario el mutexing en torno a submodules_with_errors .


Tenga en cuenta que, con Git 2.28 (tercer trimestre de 2020), la reescritura de partes del comando "git submodule" Porcelain continúa; esta vez es " git submodule set-branch " del subcomando.

Ver commit 2964d6e (02 Jun 2020) de Shourya Shukla ( periperidip ) .
(Fusionado por Junio C Hamano -- gitster -- en commit 1046282 , 25 Jun 2020)

submodule : subcomando de puerto 'set-branch' de Shell a C

Tutorizado por: Christian Couder
Tutorizado por: Kaartic Sivaraam
Ayuda: Denton Liu
Ayuda: Eric Sunshine
Ayudado por: Đoàn Trần Công Danh
Firmado por: Shourya Shukla

Convertir el subcomando del submódulo 'set-branch' en un builtin y llamarlo mediante git submodule.sh .

94voto

vogella Puntos 4884

Git 1.8.2 ha añadido la posibilidad de seguir las ramas.

# add submodule to track branch_name branch
git submodule add -b branch_name URL_to_Git_repo optional_directory_rename

# update your submodule
git submodule update --remote 

Ver también Submódulos Git

92voto

Johnny Z Puntos 846

Me gustaría añadir aquí una respuesta que en realidad es un conglomerado de otras respuestas, pero creo que puede ser más completa.

Sabes que tienes un submódulo Git cuando tienes estas dos cosas.

  1. Su .gitmodules tiene una entrada como esta:

    [submodule "SubmoduleTestRepo"]
        path = SubmoduleTestRepo
        url = https://github.com/jzaccone/SubmoduleTestRepo.git
  2. Tienes un objeto submódulo (llamado SubmoduleTestRepo en este ejemplo) en tu repositorio Git. GitHub muestra estos objetos como "submódulos". O bien git submodule status desde una línea de comandos. Los objetos submódulo Git son tipos especiales de objetos Git, y contienen la información SHA para un commit específico.

    Cada vez que se hace un git submodule update , rellenará su submódulo con el contenido del commit. Sabe dónde encontrar el commit debido a la información en el .gitmodules .

    Ahora, todos los -b hace es añadir una línea en su .gitmodules archivo. Así que siguiendo el mismo ejemplo, quedaría así:

    [submodule "SubmoduleTestRepo"]
        path = SubmoduleTestRepo
        url = https://github.com/jzaccone/SubmoduleTestRepo.git
        branch = master

    Nota: sólo se admite el nombre de la rama en un .gitmodules archivo, pero SHA y TAG no son compatibles. (en lugar de eso, la rama commit de cada módulo puede ser rastreada y actualizada usando " git add . ", por ejemplo como git add ./SubmoduleTestRepo y no es necesario cambiar el .gitmodules archivo cada vez)

    El objeto submódulo sigue apuntando a un commit específico. Lo único que el -b opción te compra es la posibilidad de añadir un --remote bandera a su actualización según la respuesta de Vogella:

    git submodule update --remote

    En lugar de poblar el contenido del submódulo a la commit apuntada por el submódulo, reemplaza esa commit con la última commit en la rama maestra, LUEGO puebla el submódulo con esa commit. Esto se puede hacer en dos pasos por la respuesta de djacobs7. Como ahora has actualizado el commit al que apunta el objeto submódulo, tienes que commit el objeto submódulo cambiado en tu repositorio Git.

    git submodule add -b no es una forma mágica de mantener todo al día con una rama. Se trata simplemente de añadir información sobre una rama en el .gitmodules y le da la opción de actualizar el objeto submódulo a la última commit de una rama especificada antes de rellenarla.

39voto

Johan Puntos 6127

Un ejemplo de cómo uso los submódulos Git.

  1. Crear un nuevo repositorio
  2. Luego clona otro repositorio como submódulo
  3. Entonces hacemos que ese submódulo utilice una etiqueta llamada V3.1.2
  4. Y luego commit.

Y eso se parece un poco a esto:

git init 
vi README
git add README
git commit 
git submodule add git://github.com/XXXXX/xxx.yyyy.git stm32_std_lib
git status

git submodule init
git submodule update

cd stm32_std_lib/
git reset --hard V3.1.2 
cd ..
git commit -a

git submodule status 

¿Tal vez ayude (aunque utilice una etiqueta y no una rama)?

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X