Manera fácil de extraer el último de todos los submódulos git
-
06-07-2019 - |
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?
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:
- 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. - para cada repositorio listado, cd en su directorio y ejecute
git checkout master & amp; & amp; git pull
. Verificar errores. - 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.
: 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