Pregunta

Estamos usando submódulos git para administrar un par de proyectos grandes que dependen de muchas otras bibliotecas que hemos desarrollado. Cada biblioteca es un repositorio separado que se incorpora al proyecto dependiente como un submódulo. Durante el desarrollo, a menudo queremos obtener la última versión de cada submódulo dependiente.

¿Tiene git un comando incorporado para hacer esto? Si no, ¿qué tal un archivo por lotes de Windows o similar que pueda hacerlo?

¿Fue útil?

Solución

Si es la primera vez revisa un repositorio, debe usar --init primero:

git submodule update --init --recursive

Para git 1.8.2 o superior, se agregó la opción --remote para permitir la actualización de los últimos consejos de sucursales remotas:

git submodule update --recursive --remote

Esto tiene el beneficio adicional de respetar cualquier " no predeterminado " ramas especificadas en los archivos .gitmodules o .git / config (si tiene alguno, el valor predeterminado es origin / master, en cuyo caso algunas de las otras respuestas aquí serían funciona bien).

Para git 1.7.3 o superior puede usar (pero los siguientes trucos sobre qué actualización todavía se aplica):

git submodule update --recursive

o:

git pull --recurse-submodules

si desea llevar sus submódulos a las últimas confirmaciones en lugar de lo que señala el repositorio.

Ver git-submodule (1) para más detalles

Otros consejos

Si necesita extraer cosas para submódulos en sus repositorios de submódulos, use

git pull --recurse-submodules
  

una característica que git aprendió por primera vez en 1.7.3.

Pero esto no verificará las confirmaciones adecuadas (a las que apunta su repositorio maestro) en submódulos

Para verificar las confirmaciones adecuadas en sus submódulos, debe actualizarlas después de usar

git submodule update --recursive --remote

En init ejecutando el siguiente comando:

git submodule update --init --recursive

desde el directorio git repo, funciona mejor para mí.

Esto extraerá todos los submódulos más recientes, incluidos

Explicado

git - the base command to perform any git command
    submodule - Inspects, updates and manages submodules.
        update - Update the registered submodules to match what the superproject
        expects by cloning missing submodules and updating the working tree of the
        submodules. The "updating" can be done in several ways depending on command
        line options and the value of submodule.<name>.update configuration variable.
            --init without the explicit init step if you do not intend to customize
            any submodule locations.
            --recursive is specified, this command will recurse into the registered
            submodules, and update any nested submodules within.

Después de esto, puede ejecutar:

git submodule update --recursive

desde el directorio git repo, funciona mejor para mí.

Esto extraerá todos los submódulos más recientes, incluidos

Nota: Esto es de 2009 y puede haber sido bueno entonces, pero ahora hay mejores opciones.

Usamos esto. Se llama git-pup :

#!/bin/bash
# Exists to fully update the git repo that you are sitting in...

git pull && git submodule init && git submodule update && git submodule status

Simplemente colóquelo en un directorio bin adecuado (/ usr / local / bin). Si está en Windows, es posible que deba modificar la sintaxis para que funcione :)

Update:

En respuesta al comentario del autor original sobre extraer todos los HEAD de todos los submódulos, esa es una buena pregunta.

Estoy bastante seguro de que git no tiene un comando para esto internamente. Para hacerlo, necesitaría identificar qué es realmente HEAD para un submódulo. Eso podría ser tan simple como decir que master es la rama más actualizada, etc. ...

Después de esto, cree un script simple que haga lo siguiente:

  1. compruebe estado del submódulo git para " modificado " repositorios El primer carácter de las líneas de salida indica esto. Si se modifica un repositorio secundario, es posible que NO desee continuar.
  2. para cada repositorio listado, cd en su directorio y ejecute git checkout master & amp; & amp; git pull . Verificar errores.
  3. Al final, le sugiero que imprima una pantalla al usuario para indicar el estado actual de los submódulos, ¿tal vez le pida que agregue todo y se comprometa?

Me gustaría mencionar que este estilo no es realmente para lo que se diseñaron los submódulos git. Por lo general, desea decir " LibraryX " está en la versión "2.32" y permanecerá así hasta que le diga "actualizar".

Eso es, en cierto sentido, lo que está haciendo con el script descrito, pero de forma más automática. ¡Se requiere cuidado!

Actualización 2:

Si está en una plataforma de Windows, es posible que desee ver el uso de Python para implementar el script, ya que es muy capaz en estas áreas. Si estás en Unix / Linux, entonces sugiero solo un script bash.

¿Necesita alguna aclaración? Simplemente publique un comentario.

Henrik está en el camino correcto. El comando 'foreach' puede ejecutar cualquier script de shell arbitrario. Dos opciones para extraer lo último podrían ser,

git submodule foreach git pull origin master

y,

git submodule foreach /path/to/some/cool/script.sh

Eso iterará a través de todos los submódulos inicializados y ejecutará los comandos dados.

Lo siguiente funcionó para mí en Windows.

git submodule init
git submodule update

Editar :

En los comentarios se señaló (por philfreo ) que se requiere la última versión. Si hay submódulos anidados que deben estar en su última versión:

git submodule foreach --recursive git pull

----- Comentarios desactualizados a continuación -----

¿No es esta la forma oficial de hacerlo?

git submodule update --init

Lo uso todo el tiempo. No hay problemas hasta ahora.

Edición :

Acabo de descubrir que puedes usar:

git submodule foreach --recursive git submodule update --init 

Que también extraerá recursivamente todos los submódulos, es decir, dependencias.

Como puede suceder que la rama predeterminada de sus submódulos sea no master , así es como automatizo las actualizaciones completas de submódulos Git:

git submodule init
git submodule update
git submodule foreach 'git fetch origin; git checkout $(git rev-parse --abbrev-ref HEAD); git reset --hard origin/$(git rev-parse --abbrev-ref HEAD); git submodule update --recursive; git clean -dfx'

Primera vez

Clon y submódulo de inicio

git clone git@github.com:speedovation/kiwi-resources.git resources
git submodule init

Descanso

Durante el desarrollo, simplemente extraiga y actualice el submódulo

git pull --recurse-submodules  && git submodule update --recursive

Actualizar submódulo Git a la última confirmación de origen

git submodule foreach git pull origin master

La forma preferida debe estar debajo

git submodule update --remote --merge

nota: los dos últimos comandos tienen el mismo comportamiento

No sé desde qué versión de git funciona, pero eso es lo que estás buscando:

git submodule update --recursive

Lo uso también con git pull para actualizar el repositorio raíz:

git pull && git submodule update --recursive

Mire http://lists.zerezo.com/git/msg674976.html que introduce un parámetro --track

Las respuestas anteriores son buenas, sin embargo, estábamos usando git-hooks para facilitar esto, pero resulta que en git 2.14 , puede configurar git config submodule.recurse a verdadero para permitir que los submódulos se actualicen cuando tire a su repositorio git.

Esto tendrá el efecto secundario de empujar todos los cambios de submódulos que tenga si están en las ramas, sin embargo, si ya necesita ese comportamiento, esto podría hacer el trabajo.

Se puede hacer usando:

git config submodule.recurse true

Git para Windows 2.6.3 :

actualización del submódulo git --rebase --remote

Hice esto adaptando gahooa 's responda arriba :

Integrarlo con un git [alias] ...

Si su proyecto principal tiene algo como esto en .gitmodules :

[submodule "opt/submodules/solarized"]
    path = opt/submodules/solarized
    url = git@github.com:altercation/solarized.git
[submodule "opt/submodules/intellij-colors-solarized"]
    path = opt/submodules/intellij-colors-solarized
    url = git@github.com:jkaving/intellij-colors-solarized.git

Agregue algo como esto dentro de su .gitconfig

[alias]
    updatesubs = "!sh -c \"git submodule init && git submodule update && git submodule status\" "

Luego, para actualizar sus submódulos, ejecute:

git updatesubs

Tengo un ejemplo de ello en mi repositorio de configuración del entorno .

Aquí está la línea de comandos para extraer de todos sus repositorios git, ya sean submódulos o no:

ROOT=$(git rev-parse --show-toplevel 2> /dev/null)
find "$ROOT" -name .git -type d -execdir git pull -v ';'

Si lo está ejecutando en su repositorio git superior, puede reemplazar " $ ROOT " en . .

Todo lo que necesitas hacer ahora es un simple git checkout

Solo asegúrese de habilitarlo a través de esta configuración global: git config --global submodule.recurse true

Desde el nivel superior en el repositorio:

git submodule foreach git checkout develop
git submodule foreach git pull

Esto cambiará todas las ramas para desarrollar y extraer las últimas

Creo que tendrás que escribir un guión para hacer esto. Para ser honesto, podría instalar python para que pueda usar os.walk para cd en cada directorio y emitir los comandos apropiados. El uso de python o algún otro lenguaje de script, que no sea por lotes, le permitiría agregar / eliminar fácilmente subproyectos sin tener que modificar el script.

Observación: no es una manera demasiado fácil, pero viable y tiene sus propios pros únicos.

Si se desea clonar solo la revisión HEAD de un repositorio y solo HEAD s de todos sus submódulos (es decir, para retirar " trunk "), entonces uno puede use el siguiente script Lua . A veces, el comando simple git submodule update --init --recursive --remote --no-fetch --depth = 1 puede provocar un error irrecuperable de git . En este caso, es necesario limpiar el subdirectorio del directorio .git / modules y clonar el submódulo manualmente usando el comando git clone --separate-git-dir . La única complejidad es encontrar URL , la ruta del directorio .git del submódulo y la ruta del submódulo en el árbol de superproyectos.

Observación

: el script solo se prueba con el repositorio https://github.com/boostorg/boost.git . Sus peculiaridades: todos los submódulos alojados en el mismo host y .gitmodules contienen solo URL s relativos.

-- mkdir boost ; cd boost ; lua ../git-submodules-clone-HEAD.lua https://github.com/boostorg/boost.git .
local module_url = arg[1] or 'https://github.com/boostorg/boost.git'
local module = arg[2] or module_url:match('.+/([_%d%a]+)%.git')
local branch = arg[3] or 'master'
function execute(command)
    print('# ' .. command)
    return os.execute(command)
end
-- execute('rm -rf ' .. module)
if not execute('git clone --single-branch --branch master --depth=1 ' .. module_url .. ' ' .. module) then
    io.stderr:write('can\'t clone repository from ' .. module_url .. ' to ' .. module .. '\n')
    return 1
end
-- cd $module ; git submodule update --init --recursive --remote --no-fetch --depth=1
execute('mkdir -p ' .. module .. '/.git/modules')
assert(io.input(module .. '/.gitmodules'))
local lines = {}
for line in io.lines() do
    table.insert(lines, line)
end
local submodule
local path
local submodule_url
for _, line in ipairs(lines) do
    local submodule_ = line:match('^%[submodule %"([_%d%a]-)%"%])
    if submodule_ then
        submodule = submodule_
        path = nil
        submodule_url = nil
    else
        local path_ = line:match('^%s*path = (.+))
        if path_ then
            path = path_
        else
            submodule_url = line:match('^%s*url = (.+))
        end
        if submodule and path and submodule_url then
            -- execute('rm -rf ' .. path)
            local git_dir = module .. '/.git/modules/' .. path:match('^.-/(.+))
            -- execute('rm -rf ' .. git_dir)
            execute('mkdir -p $(dirname "' .. git_dir .. '")')
            if not execute('git clone --depth=1 --single-branch --branch=' .. branch .. ' --separate-git-dir ' .. git_dir .. ' ' .. module_url .. '/' .. submodule_url .. ' ' .. module .. '/' .. path) then
                io.stderr:write('can\'t clone submodule ' .. submodule .. '\n')
                return 1
            end
            path = nil
            submodule_url = nil
        end
    end
end
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top