Pregunta Submódulos de Git: especifique una rama / etiqueta


Cómo git submodule add -b ¿trabajo?

Después de agregar un submódulo con una rama específica, un nuevo repositorio clonado (después git submodule update --init) estará en un compromiso específico, no en la rama en sí (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 compromiso específico, entonces, ¿cómo lo averigua?

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

PD: estoy usando 1.6.5.2.


540
2017-11-22 04:55


origen


Respuestas:


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 dices, solo un puntero a una confirmación particular del repositorio del submódulo.

Esto significa que, cuando alguien más revisa su repositorio, o extrae su código, y actualiza git submódulos, el submódulo se desprotege a esa confirmación particular.

Esto es ideal para un submódulo que no cambia a menudo, porque entonces todos en el proyecto pueden tener el submódulo en la misma confirmación.

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 que submodule_directory cambie a esa etiqueta, hace esto

git pull
git submodule update

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


571
2017-11-22 09:19



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) Usted tiene un objeto de submódulo (llamado SubmoduleTestRepo en este ejemplo) en su repositorio de git. Github muestra estos como objetos "submódulo". O hacer git submodule status desde una linea de comando Los objetos del submódulo Git son un tipo especial de objeto git y contienen la información SHA para una confirmación específica.

Cada vez que haces un git submodule update, poblará tu submódulo con contenido de la confirmación. Sabe dónde encontrar el compromiso debido a la información en el .gitmodules.

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

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

EDITAR: solo el nombre de la rama es compatible anteriormente, no SHA o TAG.

El objeto del submódulo todavía apunta a una confirmación específica. Lo único que el -b la opción compra es la posibilidad de agregar un --remote marcar a su actualización según la respuesta de Vogella:

git submodule update --remote

En lugar de rellenar el contenido del submódulo con la confirmación apuntada por el submódulo, reemplaza esa confirmación con la última confirmación en la rama maestra, LUEGO llena el submódulo con esa confirmación. Esto se puede hacer en dos pasos mediante la respuesta de djacobs7. Como ahora ha actualizado la confirmación a la que apunta el objeto del submódulo, debe enviar el objeto del submódulo modificado a su repositorio de git.

git submodule add -b no es una forma mágica de mantener todo al día con una sucursal. Simplemente agrega información sobre una rama en el .gitmodulesarchivo y le da la opción de actualizar el objeto del submódulo a la última confirmación de una rama especificada antes de poblarlo.


383
2017-09-14 02:33



Tenga en cuenta que si tienes un existente submódulo que no es rastrear una rama aún, entonces (si tienes 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úrese de que su submódulo esté realmente en 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 Repo remoto upstream el submódulo ha sido clonado desde.
UN git remote -v dentro de ese submódulo lo mostrará. Por lo general, es 'origen')

  • No olvide registrar el nuevo estado de su submódulo en su repositorio 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 para ese submódulo tendrá que usar 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+ (Q3 2016), puedes usar '.'como nombre de una rama:

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


Si desea actualizar todos sus submódulos después de una sucursal:

    git submodule update --recursive --remote

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

(Clintm notas en los comentarios eso, si corres git submodule update --remote y el sha1 resultante es el mismo que el bifurcado en el que se encuentra actualmente el submódulo, no hará nada y dejará el submódulo todavía "en esa rama" y no en el estado del cabezal separado).

Para garantizar que la rama esté realmente desprotegida (y eso no modificará el SHA1 del entrada especial representando el submódulo para el repositorio padre), 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 commits, podrá presionarlos porque serán referenciados por la rama que desea que el submódulo rastree.
Después de esa inserción dentro de un submódulo, no olvide volver al repositorio padre, agregar, confirmar y presionar el nuevo SHA1 para esos submódulos modificados.

Tenga en cuenta el uso de $toplevelrecomendado en los comentarios por Alexander Pogrebnyak.
$toplevel fue presentado en git1.7.2 en mayo de 2010: cometer f030c96.

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

dtmland agrega en los comentarios:

La secuencia de comandos foreach no podrá verificar los submódulos que no están siguiendo una bifurcación.
  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 dtmlandComando 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)'

múltiples líneas

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

241
2017-09-14 06:59



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 

Ver también Submódulos de Git


146
2018-04-03 08:44



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

  1. Crea un nuevo repositorio
  2. Luego clona otro repositorio como submódulo
  3. Entonces tenemos ese submódulo use 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 ayuda? (incluso si uso una etiqueta y no una rama)


48
2017-11-22 09:53



En mi experiencia, el cambio de ramas en el superproyecto o las cajas futuras aún provocará HEADs de submódulos separados independientemente de si el submódulo se ha agregado o rastreado correctamente (es decir, @ djacobs7 y @Johnny Z responde).

Y en lugar de verificar manualmente la rama correcta manualmente o mediante una secuencia de comandos git submódulo foreach puede ser usado.

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

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


31
2017-11-09 04:54



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

Sin embargo, esto tiene sentido cuando lo piensas bien. Digamos que creo repositorio foo con barra de submódulos. Presioné mis cambios y te digo que revises commit a7402be del repositorio foo.

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

Cuando revisa commit a7402be de repo foo, espera obtener el mismo código que presioné. Es por eso que los submódulos no se actualizan hasta que les dice explícitamente y luego realiza una nueva confirmación.

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. yo recomiendo Pro Git por Scott Chacon.


25
2017-11-22 05:22



Tengo esto en mi archivo .gitconfig. Todavía es un borrador, pero resultó útil a partir de ahora. Me ayuda a volver a conectar los submódulos a 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 = git@wherever.you.like/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-"

6
2018-04-01 16:27



Para cambiar la rama por un submódulo (suponiendo que ya tenga el submódulo como parte del repositorio):

  • cd a la raíz de su repos que contiene los submódulos
  • Abierto .gitmodules para editar
  • Añadir línea abajo path = ... y url = ... que dice branch = your-branchpara cada submódulo; guardar el archivo .gitmodules.
  • luego sin cambiar el directorio do $ git submodule update --remote

... esto debería extraer los últimos commits en la rama especificada, para cada submódulo así modificado.


6
2018-06-12 13:34



Usamos Curandero para extraer el módulo específico de otro repositorio git. Necesitamos extraer el código sin la base de códigos completa del repositorio proporcionado, necesitamos un módulo / archivo muy específico de ese enorme repositorio y debería actualizarse cada vez que ejecutemos la actualización.

Así que logramos de esta manera,

Crear configuración 

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 1 directorio del repositorio github provisto como se especifica en la configuración del primer módulo, y el otro es extraer y crear el archivo del repositorio dado.

Otros desarrolladores solo necesitan correr

$ quack

Y extrae el código de las configuraciones anteriores.


3
2017-10-22 14:35



Elegir una rama para un submódulo tiene el único efecto de dejar que git checkout se desconecte en el estado HEAD (si está predeterminado) --checkout comportamiento se selecciona) la última confirmación de esa rama seleccionada cuando pasa el --remoteopción en el git submodule update línea de comando.

Tenga en cuenta que la rama que elija para este fin en la configuración del submódulo NO ES el que será clonado durante submodule update --remote. Como una consecuencia sutil si pasas también el --depth parámetro y no instruyes a git sobre qué rama quieres clonar - !! y en realidad no puedes en la línea de comandos de actualización del submódulo git !! -, se comportará implícitamente como se explica en git-clone(1) docu para git clone --single-branch CON FALTA explícita --branch parámetro y por lo tanto solo clonará la rama primaria. Sin sorpresa, en la etapa de clonación y cuando finalmente tratará de encontrar la última confirmación para la rama que eligió para el submódulo, si esta no es la primaria, fallará con

fatal: se necesitaba una sola revisión

No se puede encontrar el origen actual /NonPrimaryBranch revisión en la ruta del submódulo 'mySubmodule'


-1
2018-05-29 15:52