Tengo un proyecto con un submódulo Git. Es de un ssh: // ... URL, y está en commit A. El commit B ha sido enviado a ese URL, y quiero que el submódulo recupere el commit y lo cambie.
Ahora, entiendo que git submodule update
debería hacer esto, pero no es así. No hace nada (sin salida, código de salida exitoso). Aquí hay un ejemplo:
$ mkdir foo
$ cd foo
$ git init .
Initialized empty Git repository in /.../foo/.git/
$ git submodule add ssh://user@host/git/mod mod
Cloning into mod...
user@host's password: hunter2
remote: Counting objects: 131, done.
remote: Compressing objects: 100% (115/115), done.
remote: Total 131 (delta 54), reused 0 (delta 0)
Receiving objects: 100% (131/131), 16.16 KiB, done.
Resolving deltas: 100% (54/54), done.
$ git commit -m "Hello world."
[master (root-commit) 565b235] Hello world.
2 files changed, 4 insertions(+), 0 deletions(-)
create mode 100644 .gitmodules
create mode 160000 mod
# At this point, ssh://user@host/git/mod changes; submodule needs to change too.
$ git submodule init
Submodule 'mod' (ssh://user@host/git/mod) registered for path 'mod'
$ git submodule update
$ git submodule sync
Synchronizing submodule url for 'mod'
$ git submodule update
$ man git-submodule
$ git submodule update --rebase
$ git submodule update
$ echo $?
0
$ git status
# On branch master
nothing to commit (working directory clean)
$ git submodule update mod
$ ...
También he intentado git fetch mod
, que parece hacer una zona de alcance (pero posiblemente no pueden, porque no se pida la contraseña!), Pero git log
y git show
negar la existencia de nuevas confirmaciones. Hasta ahora solo he estado rm
aplicando el módulo y volviéndolo a agregar, pero esto es incorrecto en principio y tedioso en la práctica.
git
git-submodules
git-pull
Thanatos
fuente
fuente
--remote
opción, ¿tal vez sería útil marcar eso como la respuesta aceptada en lugar del enfoque "a mano" en la respuesta de Jason?--remote
es definitivamente una mejor solución en este momento, y dado que esta pregunta se ha vinculado desde un Github Gist sobre submódulos, creo que sería mejor para los lectores entrantes ver la nueva respuesta.hunter2
contraseña: o)Respuestas:
El
git submodule update
comando en realidad le dice a Git que desea que sus submódulos verifiquen la confirmación ya especificada en el índice del superproyecto. Si desea actualizar sus submódulos a la última confirmación disponible desde su control remoto, deberá hacerlo directamente en los submódulos.Entonces en resumen:
O, si eres una persona ocupada:
fuente
git submodule foreach git pull
git submodule foreach git pull origin master
.git submodule foreach --recursive git pull origin master
.-a
interruptor paragit commit
"Dígale al comando que organice automáticamente los archivos que han sido modificados y eliminados, pero los archivos nuevos que no le ha dicho a Git no se ven afectados".Git 1.8.2 presenta una nueva opción
--remote
, que permitirá exactamente este comportamiento. Corriendobuscará los últimos cambios desde la parte superior en cada submódulo, los combinará y verificará la última revisión del submódulo. Como dice la documentación :
Esto es equivalente a ejecutarse
git pull
en cada submódulo, que generalmente es exactamente lo que desea.fuente
git pull
en cada submódulo" Para aclarar, no hay diferencia (desde la perspectiva del usuario) entre su respuesta ygit submodule foreach git pull
?foreach git pull
solo los verificó, pero no actualizó el puntero del repositorio principal para apuntar a la confirmación más reciente del submódulo. Solo con--remote
eso hizo que apuntara a la última confirmación.En el directorio padre de su proyecto, ejecute:
O si tiene submódulos recursivos ejecute:
A veces esto todavía no funciona, porque de alguna manera tiene cambios locales en el directorio de submódulos local mientras se actualiza el submódulo.
La mayoría de las veces, el cambio local podría no ser el que desea cometer. Puede suceder debido a la eliminación de un archivo en su submódulo, etc.
fuente
Su proyecto principal apunta a un compromiso particular en el que debe estar el submódulo.
git submodule update
intenta verificar esa confirmación en cada submódulo que se ha inicializado. El submódulo es realmente un repositorio independiente: solo crea una nueva confirmación en el submódulo y empujar eso no es suficiente. También debe agregar explícitamente la nueva versión del submódulo en el proyecto principal.Entonces, en su caso, debe encontrar la confirmación correcta en el submódulo; supongamos que esa es la punta de
master
:Ahora regrese al proyecto principal, organice el submódulo y confirme que:
Ahora empuje su nueva versión del proyecto principal:
A partir de este momento, si alguien más actualiza su proyecto principal, entonces
git submodule update
ellos actualizarán el submódulo, suponiendo que se haya inicializado.fuente
Parece que dos escenarios diferentes se mezclan en esta discusión:
escenario 1
Utilizando los punteros de mi repositorio principal para los submódulos, quiero verificar la confirmación en cada submódulo al que apunta el repositorio principal, posiblemente después de iterar primero a través de todos los submódulos y actualizar / extraerlos desde el control remoto.
Esto es, como se señaló, hecho con
Escenario 2, que creo que es a lo que apunta OP
Han ocurrido cosas nuevas en uno o más submódulos, y quiero 1) extraer estos cambios y 2) actualizar el repositorio principal para que apunte a la confirmación HEAD (más reciente) de este / estos submódulos.
Esto sería hecho por
No es muy práctico, ya que tendría que codificar n rutas a todos los n submódulos en, por ejemplo, un script para actualizar los punteros de confirmación del repositorio principal.
Sería genial tener una iteración automatizada a través de cada submódulo, actualizando el puntero del repositorio principal (usando
git add
) para apuntar a la cabeza del submódulo (s).Para esto, hice este pequeño script Bash:
git-update-submodules.sh
Para ejecutarlo, ejecuta
Elaboración
En primer lugar, supongo que la rama con el nombre $ BRANCH (segundo argumento) existe en todos los repositorios. Siéntase libre de hacer esto aún más complejo.
El primer par de secciones son algunas comprobaciones de que los argumentos están ahí. Luego saco las últimas cosas del repositorio principal (prefiero usar --ff (avance rápido) cada vez que solo hago pulls. Tengo rebase, BTW).
Entonces, puede ser necesario inicializar algunos submódulos, si se han agregado nuevos submódulos o aún no se han inicializado:
Luego actualizo / extraigo todos los submódulos:
Observe algunas cosas: en primer lugar, estoy encadenando algunos comandos de Git usando
&&
, lo que significa que el comando anterior debe ejecutarse sin error.Después de una posible extracción exitosa (si se encontraron cosas nuevas en el control remoto), hago un esfuerzo para asegurarme de que un posible compromiso de fusión no se quede atrás en el cliente. Nuevamente, solo sucede si un tirón realmente trajo cosas nuevas.
Finalmente, la final
|| true
es asegurar que el script continúe con los errores. Para que esto funcione, todo en la iteración debe estar entre comillas dobles y los comandos Git están entre paréntesis (precedencia del operador).Mi parte favorita:
Itere todos los submódulos, con
--quiet
, lo que elimina la salida 'Entrar en MODULE_PATH'. Usando'echo $path'
(debe estar entre comillas simples), la ruta al submódulo se escribe en la salida.Esta lista de rutas relativas de submódulos se captura en una matriz (
$(...)
): finalmente repita esto ygit add $i
actualice el repositorio principal.Finalmente, una confirmación con algún mensaje que explica que se actualizó el repositorio principal. Este commit será ignorado por defecto, si no se hizo nada. Empuje esto al origen, y ya está.
Tengo un script que ejecuta esto en un trabajo de Jenkins que luego se encadena a una implementación automática programada, y funciona de maravilla.
Espero que esto sea de ayuda para alguien.
fuente
pwd
comando imprime la 'ruta absoluta' adecuada para cada submódulo presente;--recursive
asegura que visitamos todos los submódulos, incluidos los submódulos-dentro de submódulos -... que pueden estar presentes en un proyecto grande. Ambos métodos causan problemas con los directorios que incluyen espacios, por ejemplo, la/c/Users/Ger/Project\ Files/...
política es nunca usar espacios en blanco en ningún lugar de nuestros proyectos.--remote
opción.git submodule update --remote
se comporta aproximadamente como lo hace tu script.The remote branch used defaults to master, but the branch name may be overridden by setting the submodule.<name>.branch option in either .gitmodules or .git/config (with .git/config taking precedence).
no quiero editar .gitmodules ni .git / config cada vez que quiero hacer esto en otra rama que no sea master. Pero tal vez me he perdido algo? Además, el método parece imponer fusiones recursivas (por lo que se pierde la posibilidad de un avance rápido).Simple y simple, para buscar los submódulos:
Y ahora continúe actualizándolos a la última rama maestra (por ejemplo):
fuente
Tenga en cuenta que, aunque la forma moderna de actualizar las confirmaciones de submódulos sería:
La forma más antigua era:
Excepto ... esta segunda forma no es realmente "tranquila".
Ver commit a282f5a (12 abr 2019) por Nguyễn Thái Ngọc Duy (
pclouds
) .(Fusionada por Junio C Hamano -
gitster
- en commit f1c9f6c , 25 abr 2019)Y Git 2.23 (Q3 2019) soluciona otro problema: "
git submodule foreach
" no protegió las opciones de línea de comando que se pasaron al comando para ejecutarse correctamente en cada submódulo cuando la--recursive
opción " " estaba en uso.Ver commit 30db18b (24 de junio de 2019) por Morian Sonnet (
momoson
) .(Fusión por Junio C Hamano -
gitster
- en commit 968eecb , 09 jul 2019)fuente
Esto extraerá todos los últimos commits.
fuente
En mi caso, quería
git
actualizar a la última versión y, al mismo tiempo, volver a llenar los archivos faltantes.Lo siguiente restauró los archivos faltantes (gracias a los
--force
cuales no parece haber sido mencionado aquí), pero no obtuvo ninguna confirmación nueva:git submodule update --init --recursive --force
Esto hizo:
git submodule update --recursive --remote --merge --force
fuente
@ Jason es correcto en cierto modo, pero no del todo.
Entonces,
git submodule update
realiza el pago, pero es para confirmar en el índice del repositorio que contiene. Todavía no conoce el nuevo compromiso en sentido ascendente. Vaya a su submódulo, obtenga la confirmación que desea y confirme el estado del submódulo actualizado en el repositorio principal y luego haga logit submodule update
.fuente
git submodule update
, la actualización moverá el submódulo a la confirmación especificada en el HEAD actual del superproyecto. (cualquiera que sea la confirmación más reciente en el superproyecto dice que el subproyecto debería estar en - este comportamiento, después de la explicación en la publicación de Jason, me parece lógico) También parece buscar, pero solo en el caso de que el subproyecto esté en la confirmación incorrecta , lo que se sumaba a mi confusión.Aquí hay una frase increíble para actualizar todo a lo último en master:
Gracias a Mark Jaquith
fuente
Si no conoce la rama host, haga esto:
Obtendrá una rama del repositorio principal de Git y luego, para cada submódulo, extraerá la misma rama.
fuente
Si está buscando la
master
rama de pago para cada submódulo, puede usar el siguiente comando para ese propósito:fuente