repositorio - Manera fácil de sacar lo último de todos los submódulos de git
git push (17)
Estamos utilizando los submódulos de git para administrar un par de grandes proyectos que dependen de muchas otras bibliotecas que hemos desarrollado. Cada biblioteca es un repositorio separado incluido en el proyecto dependiente como un submódulo. Durante el desarrollo, a menudo queremos simplemente tomar la última versión de cada submódulo dependiente.
¿Git tiene un comando incorporado para hacer esto? Si no, ¿qué tal un archivo por lotes de Windows o similar que pueda hacerlo?
En init ejecutando el siguiente comando:
git submodule update --init --recursive
Desde dentro del directorio git repo, funciona mejor para mí.
Esto tirará de todos los últimos submódulos 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 puedes simplemente correr:
git submodule update --recursive
Desde dentro del directorio git repo, funciona mejor para mí.
Esto tirará de todos los últimos submódulos 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.
any submodule locations.
--recursive is specified, this command will recurse into the registered
submodules, and update any nested submodules within.
Primera vez
Clon y Init Submodule
git clone [email protected]:speedovation/kiwi-resources.git resources
git submodule init
Descanso
Durante el desarrollo solo tira y actualiza el submódulo.
git pull --recurse-submodules && git submodule update --recursive
Actualizar el submódulo de Git al último commit en origen
git submodule foreach git pull origin master
La forma preferida debe estar por debajo
git submodule update --remote --merge
Nota: los dos últimos comandos tienen el mismo comportamiento.
Aquí está la línea de comandos para extraer de todos tus repositorios de git, sean o no submódulos:
ROOT=$(git rev-parse --show-toplevel 2> /dev/null)
find "$ROOT" -name .git -type d -execdir git pull -v '';''
Si lo ejecuta en su repositorio de git superior, puede reemplazar "$ROOT"
en .
.
Como puede suceder que la rama predeterminada de sus submódulos no sea master
, así es como automatizo las actualizaciones completas de los submódulos de 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''
Creo que tendrás que escribir un guión para hacer esto. Para ser honesto, podría instalar python para hacerlo, de modo que pueda usar os.walk
para os.walk
a 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 subproyectos fácilmente sin tener que modificar el script.
Git para windows 2.6.3 :
git submodule update --rebase --remote
Henrik está en el camino correcto. El comando ''foreach'' puede ejecutar cualquier script de shell arbitrario. Dos opciones para sacar lo último podrían ser,
git submodule foreach git pull origin master
y,
git submodule foreach /path/to/some/cool/script.sh
Eso recorrerá todos los submódulos inicializados y ejecutará los comandos dados.
Las respuestas anteriores son buenas, sin embargo, estábamos usando git-hooks para hacer esto más fácil, pero resulta que en git 2.14 , puedes configurar git config submodule.recurse
en true para permitir que los submódulos se actualicen cuando accedas a tu repositorio de git.
Esto tendrá el efecto secundario de empujar todos los cambios de submódulos que tienes si están en las sucursales, pero si ya necesitas ese comportamiento, esto podría funcionar.
Lo siguiente me funcionó en Windows.
git submodule init
git submodule update
Mire http://lists.zerezo.com/git/msg674976.html que introduce un parámetro --track
No sé desde qué versión de git está funcionando, pero eso es lo que estás buscando:
git submodule update --recursive
Lo uso con git pull
para actualizar el repositorio raíz, también:
git pull && git submodule update --recursive
Observación: no es una forma demasiado fácil, pero es viable y tiene sus propias ventajas únicas.
Si uno quiere clonar solo la revisión HEAD
de un repositorio y solo HEAD
s de todos sus submódulos (es decir, para "troncalizar"), entonces puede usar el siguiente script de Lua . A veces, el comando simple git submodule update --init --recursive --remote --no-fetch --depth=1
puede provocar un error de git
irrecuperable. En este caso, es necesario limpiar el subdirectorio del directorio .git/modules
y clonar el submódulo manualmente usando el git clone --separate-git-dir
. La única complejidad es encontrar la URL , la ruta del directorio .git
del submódulo y la ruta del submódulo en el árbol de superproyectos.
Nota: el script solo se prueba en el repositorio https://github.com/boostorg/boost.git
. Sus peculiaridades: todos los submódulos alojados en el mismo host y .gitmodules
contienen solo .gitmodules
URL relativas.
-- 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
Si necesita juntar 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 comprueba las confirmaciones adecuadas (a las que apunta su repositorio principal) en los submódulos
Para verificar las confirmaciones adecuadas en sus submódulos, debe actualizarlos después de tirar usando
git submodule update --recursive --remote
Hice esto adaptando la respuesta de 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 = [email protected]:altercation/solarized.git
[submodule "opt/submodules/intellij-colors-solarized"]
path = opt/submodules/intellij-colors-solarized
url = [email protected]:jkaving/intellij-colors-solarized.git
Agrega algo como esto dentro de tu .gitconfig
[alias]
updatesubs = "!sh -c /"git submodule init && git submodule update && git submodule status/" "
Luego para actualizar tus submódulos, ejecuta:
git updatesubs
Tengo un example de ello en mi entorno de configuración de repositorio .
Editar :
En los comentarios se señaló (por philfreo ) que se requiere la última versión. Si hay algún submódulo anidado que deba estar en su última versión:
git submodule foreach --recursive git pull
----- Comentario obsoleto a continuación -----
¿No es esta la manera oficial de hacerlo?
git submodule update --init
Lo uso todo el tiempo. No hay problemas hasta ahora.
Editar:
Acabo de encontrar que puedes usar:
git submodule foreach --recursive git submodule update --init
Lo que también tirará recursivamente de todos los submódulos, es decir, dependencias.
Nota: Esto es de 2009 y puede haber sido bueno entonces, pero ahora hay mejores opciones.
Nosotros 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 :)
Actualizar:
En respuesta al comentario del autor original sobre la introducción de todos los encabezados 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, deberías identificar qué es HEAD realmente para un submódulo. Eso podría ser tan simple como decir que master
es la rama más actualizada, etc ...
A continuación, cree un script simple que haga lo siguiente:
- Verifique el
git submodule status
para los repositorios "modificados". El primer carácter de las líneas de salida indica esto. Si se modifica un sub-repositorio, es posible que NO desee continuar. - para cada repo listado, cd en su directorio y ejecute
git checkout master && git pull
. Compruebe si hay errores. - Al final, le sugiero que imprima una pantalla al usuario para indicar el estado actual de los submódulos, ¿quizás 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 de git. Típicamente, usted quiere decir que "LibraryX" está en la versión "2.32" y permanecerá así hasta que le diga que "actualice".
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 se encuentra en una plataforma de Windows, es posible que desee utilizar Python para implementar el script, ya que es muy capaz en estas áreas. Si estás en Unix / Linux, entonces sugiero un script bash.
¿Necesita alguna aclaración? Solo publica un comentario.
Para git 1.8.2 o superior, la opción --remote
se agregó para admitir la actualización de las últimas sugerencias de sucursales remotas:
git submodule update --recursive --remote
Esto tiene el beneficio adicional de respetar cualquier rama "no predeterminada" especificada en los .gitmodules
o .git/config
(si tiene alguna, la predeterminada es origin / master, en cuyo caso algunas de las respuestas aquí funcionarán como bien).
Para git 1.7.3 o superior puede usar (pero los errores que se detallan a continuación sobre qué actualización se aplica):
git submodule update --recursive
o:
git pull --recurse-submodules
si quieres tirar de tus submódulos a las últimas confirmaciones en lugar de lo que apunta el repositorio.
Nota: Si es la primera vez que contratas un repositorio, debes usar --init
primero:
git submodule update --init --recursive
Para mayores, git 1.6.1 o superior puedes usar algo similar a (modificado para adaptarse):
git submodule foreach git pull origin master
Ver git-submodule(1) para más detalles.