tag remove remota rama example crear cambiar git git-submodules

remove - git push tag



¿Cómo puedo especificar una rama/etiqueta al agregar un submódulo Git? (11)

De acuerdo con mi experiencia, cambiar de rama en el superproyecto o en las verificaciones futuras seguirá causando HEADs de submódulos separados, independientemente de que el submódulo se haya agregado y rastreado correctamente (es decir, respuestas de @ djacobs7 y @Johnny Z).

Y en lugar de revisar manualmente la rama correcta manualmente o mediante un script, se puede utilizar un submódulo de git para cada uno.

Esto verificará el archivo de configuración del submódulo para la propiedad de la rama y verificará la rama establecida.

git submodule foreach -q --recursive ''branch="$(git config -f <path>.gitmodules submodule.$name.branch)"; git checkout $branch''

¿Cómo funciona git submodule add -b ?

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

No puedo encontrar ninguna información en .gitmodules o .git/config acerca de la rama del submódulo o cualquier compromiso específico, entonces, ¿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.


Elegir una rama para un submódulo tiene el único efecto de permitir que Git verifique en un estado HEAD separado (si se selecciona el comportamiento predeterminado de --checkout ) la última confirmación de esa rama seleccionada cuando pase la opción --remote en el git submodule update línea de comandos.

Tenga en cuenta que la rama que elija para este propósito en la configuración de submódulos NO ES la que se clonará durante la submodule update --remote . Como consecuencia sutil, si pasa también el parámetro --depth y no le indica a Git qué rama desea clonar - !! y en realidad no puedes en la línea de comandos de actualización de submódulo de Git !! -, se comportará implícitamente como se explica en la documentación de git-clone(1) para el git clone --single-branch con el parámetro explícito --branch faltante , y por lo tanto solo --branch la rama principal .

Sin sorpresa, al final de la etapa de clonación, cuando finalmente intentará encontrar la última confirmación para la rama que eligió para el submódulo, si esta no es la principal, fallará con

fatal: Necesitaba una sola revisión

No se puede encontrar la revisión de origen / nonPrimaryBranch actual en la ruta de submódulo ''mySubmodule''


Git 1.8.2 agregó la posibilidad de rastrear sucursales.

# add submodule to track master branch git submodule add -b master [URL to Git repo]; # update your submodule git submodule update --remote

Véase también Git submódulos.


Los submódulos de Git son un poco extraños (siempre están en modo "cabeza separada"), no se actualizan a la última confirmación en una rama como se podría esperar.

Sin embargo, esto tiene algún sentido cuando lo piensas. Digamos que creo foo repositorio con barra de submódulo. Presiono mis cambios y te digo que compruebes el commit a7402be del repositorio foo .

Luego imagine que alguien realiza un cambio en la barra de repositorio antes de que pueda hacer su clon.

Cuando verifica el commit a7402be del repositorio foo , espera obtener el mismo código que presioné. Es por eso que los submódulos no se actualizan hasta que se les dice explícitamente y luego hacen un nuevo compromiso.

Personalmente creo que los submódulos son la parte más confusa de Git. Hay muchos lugares que pueden explicar los submódulos mejor que yo. Recomiendo Pro Git por Scott Chacon.


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

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

  1. Tu .gitmodules tiene una entrada como esta:

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

  2. Tiene un objeto de submódulo (denominado SubmoduleTestRepo en este ejemplo) en su repositorio Git. GitHub muestra como objetos "submódulos". O hacer git submodule status desde una línea de comando. Los objetos de submódulos de Git son tipos especiales de objetos de Git y contienen la información de SHA para un compromiso específico.

    Cada vez que realice una git submodule update , rellenará su submódulo con el contenido de la confirmación. Sabe dónde encontrar la confirmación debido a la información en los .gitmodules .

    Ahora, todo lo que hace -b es agregar una línea en su archivo .gitmodules . Así que siguiendo el mismo ejemplo se vería así:

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

    EDITAR: solo se admite el nombre de rama arriba, no SHA o TAG.

    El objeto de submódulo todavía apunta a un compromiso específico. Lo único que la opción -b te compra es la posibilidad de agregar una --remote a tu actualización según la respuesta de Vogella:

    git submodule update --remote

    En lugar de rellenar el contenido del submódulo al compromiso señalado por el submódulo, reemplaza ese compromiso con el último compromiso en la rama maestra, ENTONCES llena el submódulo con ese compromiso. Esto se puede hacer en dos pasos por djacobs7 respuesta. Como ya ha actualizado la confirmación a la que apunta el objeto de submódulo, debe confirmar la modificación del objeto de submódulo en su repositorio Git.

    git submodule add -b no es una forma mágica de mantener todo actualizado con una sucursal. Simplemente agrega información sobre una rama en el archivo .gitmodules y le da la opción de actualizar el objeto de submódulo a la última confirmación de una rama específica antes de .gitmodules .


Nota: Git 1.8.2 agregó la posibilidad de rastrear sucursales. 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 usted dice, solo un puntero a un compromiso particular del repositorio del submódulo.

Esto significa que, cuando alguien más verifica su repositorio, o extrae su código, y realiza la actualización de submódulos de git, el submódulo se revisa para ese compromiso en particular.

Esto es excelente para un submódulo que no cambia con frecuencia, porque entonces todos los participantes en el proyecto pueden tener el submódulo en el mismo compromiso.

Si desea mover el submódulo a una etiqueta en particular:

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

Luego, otro desarrollador que quiere tener submodule_directory cambiado a esa etiqueta, hace esto

git pull git submodule update

git pull cambia git pull cambios que comprometen sus puntos de directorio de submódulos. git submodule update realidad se fusiona en el nuevo código.


Para cambiar de rama a un submódulo (asumiendo que ya tiene el submódulo como parte del repositorio):

  • cd a la raíz de su repositorio que contiene los submódulos
  • Abre .gitmodules para editar
  • Agregue la línea debajo de la path = ... y url = ... que dice branch = your-branch , para cada submódulo; guardar archivo .gitmodules .
  • entonces sin cambiar el directorio do $ git submodule update --remote

... esto debería incluir las últimas confirmaciones en la rama especificada, para cada submódulo así modificado.


Tenga en cuenta que si tiene un submódulo que aún no está rastreando una rama , entonces ( si tiene git 1.8.2+ ):

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

    cd /path/to/your/parent/repo git config -f .gitmodules submodule.<path>.branch <branch>

  • Asegúrate de que tu submódulo esté realmente a la última 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

(con "origen" es el nombre del repositorio remoto en sentido ascendente desde donde se ha clonado el submódulo.
Un git remote -v dentro de ese submódulo lo mostrará. Por lo general, es ''origen'')

  • No olvide grabar el nuevo estado de su submódulo en su repositorio de padres:

    cd /path/to/your/parent/repo git add path/to/your/submodule git commit -m "Make submodule tracking a branch"

  • Las actualizaciones subsiguientes para ese submódulo deberán usar la opción --remote :

    # 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+ (Q3 2016), puede usar '' . ''como nombre de rama:

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

Si desea actualizar todos sus submódulos siguiendo una rama:

git submodule update --recursive --remote

Tenga en cuenta que el resultado, para cada submódulo actualizado, será casi siempre una CABEZA separada , como lo señala Dan Cameron en su respuesta .

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

Para asegurarse de que la rama esté realmente retirada (y eso no modificará el SHA1 de la entrada especial que representa el submódulo para el repositorio principal), sugiere:

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

Cada submódulo seguirá haciendo referencia al mismo SHA1, pero si realiza nuevos confirmaciones, podrá presionarlos porque la rama a la que desea hacer referencia el submódulo hará referencia a ellos.
Después de ese empuje dentro de un submódulo, no olvide volver al repositorio principal, agregue, confirme y presione el nuevo SHA1 para esos submódulos modificados.

Tenga en cuenta el uso de $toplevel , recomendado en los comentarios de 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 está .gitmodules ).

dtmland añade en los comentarios :

La secuencia de comandos foreach no podrá enviar los submódulos que no están siguiendo una rama.
Sin embargo, este comando le da a ambos:

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

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

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

líneas múltiples:

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


Tengo esto en mi archivo .gitconfig. Todavía es un borrador, pero resultó útil a partir de ahora. Me ayuda a siempre volver a colocar los submódulos en su rama.

[alias] ###################### # #Submodules aliases # ###################### #git sm-trackbranch : places all submodules on their respective branch specified in .gitmodules #This works if submodules are configured to track a branch, i.e if .gitmodules looks like : #[submodule "my-submodule"] # path = my-submodule # url = [email protected]/my-submodule.git # branch = my-branch sm-trackbranch = "! git submodule foreach -q --recursive ''branch=/"$(git config -f $toplevel/.gitmodules submodule.$name.branch)/"; git checkout $branch''" #sm-pullrebase : # - pull --rebase on the master repo # - sm-trackbranch on every submodule # - pull --rebase on each submodule # # Important note : #- have a clean master repo and subrepos before doing this ! #- this is *not* equivalent to getting the last committed # master repo + its submodules: if some submodules are tracking branches # that have evolved since the last commit in the master repo, # they will be using those more recent commits ! # # (Note : On the contrary, git submodule update will stick #to the last committed SHA1 in the master repo) # sm-pullrebase = "! git pull --rebase; git submodule update; git sm-trackbranch ; git submodule foreach ''git pull --rebase'' " # git sm-diff will diff the master repo *and* its submodules sm-diff = "! git diff && git submodule foreach ''git diff'' " #git sm-push will ask to push also submodules sm-push = push --recurse-submodules=on-demand #git alias : list all aliases #useful in order to learn git syntax alias = "!git config -l | grep alias | cut -c 7-"


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

  1. Crear un nuevo repositorio
  2. Luego clona otro repositorio como un submódulo
  3. Luego tenemos ese submódulo de usar una etiqueta llamada V3.1.2
  4. Y luego nos comprometemos.

Y eso se ve un poco así:

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 use una etiqueta y no una rama)?


Usamos Quack para extraer un módulo específico de otro repositorio Git. Necesitamos obtener el código sin la base de código completa del repositorio provisto. Necesitamos un módulo / archivo muy específico de ese enorme repositorio y debemos actualizarlo cada vez que ejecutemos una actualización.

Así lo logramos de esta manera:

Crear configuracion

name: Project Name modules: local/path: repository: https://github.com/<username>/<repo>.git path: repo/path branch: dev other/local/path/filename.txt: repository: https://github.com/<username>/<repo>.git hexsha: 9e3e9642cfea36f4ae216d27df100134920143b9 path: repo/path/filename.txt profiles: init: tasks: [''modules'']

Con la configuración anterior, crea un directorio desde el repositorio provisto de GitHub como se especifica en la configuración del primer módulo, y el otro es extraer y crear un archivo desde el repositorio dado.

Otros desarrolladores solo necesitan ejecutar

$ quack

Y saca el código de las configuraciones anteriores.