306 votos

Actualización de git submódulo

Tengo un proyecto con un git submódulo. Es a partir de ssh://... URL, y es en cometer A. Cometer B ha sido empujado a esa URL, y quiero que el submódulo para la recuperación de la confirmación, y cambiar a ella.

Ahora, a mi entender se que git submodule update debería hacer esto, pero no es así. De no hacer nada (no hay salida, el éxito, el código de salida). He aquí 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 to.
$ 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, lo que parece hacer un fetch (pero no puede, porque no pide una contraseña!), pero git log y git show negar la existencia de los nuevos commits. Hasta ahora sólo he sido rm ing el módulo y vuelva a agregar, pero esto es incorrecto, en principio y tedioso en la práctica.

Gracias por toda la ayuda...

527voto

Jason Puntos 3139

La git submodule update comando le dice a git que desea utilizar cualquier cometer estado está desprotegido en su submódulos. Si desea actualizar los submódulos, usted necesitará hacer esto directamente en su submódulos.

Así que en resumen:

# get the submodule initially
git submodule add ssh://bla submodule_dir
git submodule init

# time passes, submodule upstream is updated
# and you now want to update

# change to the submodule directory
cd submodule_dir

# checkout desired branch
git checkout master

# update
git pull

# get back to your project root
cd ..

# now the submodules are in the state you want, so
git commit -am "Pulled down update to submodule_dir"

O, si usted está muy ocupado persona:

git submodule foreach git pull origin master

106voto

David Z Puntos 49476

git 1.8.2 características de una nueva opción --remote que permitirá exactamente este comportamiento. Ejecución

git submodule update --remote --merge

va a obtener los últimos cambios de aguas en cada submódulo, de combinación de ellos, y echa un vistazo a la última revisión de la submódulo. Esto es equivalente a ejecutar git pull en cada submódulo, que generalmente es exactamente lo que usted desea.

47voto

pinux Puntos 426

en su proyecto de directorio padre de ejecución:

git submodule update --init 

o si usted tiene recursiva submódulos ejecutar:

git submodule update --init --recursive

a veces esto no funciona es porque de alguna manera tiene cambios locales en el local submódulo de directorio, mientras que el submódulo está siendo actualizada.

La mayoría de las veces el cambio local podría no ser el que usted desea confirmar. Puede suceder debido a un archivo de la eliminación en el submódulo etc. Si es así, hacer un reset en tu local submódulo de directorio y en su proyecto de directorio padre ejecute de nuevo:

git submodule update --init --recursive 

43voto

Mark Longair Puntos 93104

Su principal proyecto apunta a un particular, se comprometen a que la submódulo debe ser de al. ¿Cuál git submodule update hace es tratar a la caja que se cometen en cada submódulo que ha sido inicializado. El submódulo es realmente un repositorio independiente - la creación de un nuevo compromiso en el submódulo, y empujando eso no es suficiente, también es necesario añadir explícitamente la nueva versión del submódulo en el proyecto principal.

Así que, en su caso, usted debe encontrar el correcto compromiso en el submódulo - supongamos que la punta del maestro:

cd mod
git checkout master
git pull origin master

Ahora volver a la principal proyecto, la etapa de la submódulo y se comprometen a que:

cd ..
git add mod
git commit -m "Updating the submodule 'mod' to the latest version"

Ahora empuja la nueva versión del proyecto principal:

git push origin master

A partir de este punto, si nadie las actualizaciones de su proyecto principal, a continuación, git submodule update de ellos va a actualizar el submódulo, asumiendo que ha sido inicializado.

9voto

Parece como 2 escenarios diferentes se mezclan en esta discusión:

Escenario 1

El uso de mi padre repo de punteros a submódulos, quiero ver la confirmación en cada submódulo, que el padre repo que apunta, posiblemente después de la primera iteración a través de todos los submódulos y la actualización y/o extracción de estos remoto.

Este es, como se ha señalado, hecho con

git submodule foreach git pull origin BRANCH
git submodule update

El escenario 2, que creo que es lo que OP es el objetivo en

Lo nuevo que ha sucedido en 1 o más submódulos, y quiero 1) tire de estos cambios, y 2) la actualización de los padres de repo para que apunte a la HEAD (el más reciente) confirmación de este/estos submódulos.

Esto se haría por

git submodule foreach git pull origin BRANCH
git add module_1_name
git add module_2_name
......
git add module_n_name
git push origin BRANCH

No es muy práctico, ya que tendría que codificar n rutas a todos los n submódulos en, por ejemplo, un script de actualización de los padres de repos a comprometer a los punteros.

Lo que estaría bien sería para un sistema automatizado de iteración a través de cada submódulo, la actualización de los padres de los repos de puntero (usando git add) para que apunte a la cabeza de la submódulo(s).

Para esto, he hecho esta pequeña bash-script:

git-update-submodules.sh

#!/bin/bash

APP_PATH=$1
shift

if [ -z $APP_PATH ]; then
  echo "Missing 1st argument: should be path to folder of a git repo";
  exit 1;
fi

BRANCH=$1
shift

if [ -z $BRANCH ]; then
  echo "Missing 2nd argument (branch name)";
  exit 1;
fi

echo "Working in: $APP_PATH"
cd $APP_PATH

git checkout $BRANCH && git pull --ff origin $BRANCH

git submodule sync
git submodule init
git submodule update
git submodule foreach "(git checkout $BRANCH && git pull --ff origin $BRANCH && git push origin $BRANCH) || true"

for i in $(git submodule foreach --quiet 'echo $path')
do
  echo "Adding $i to root repo"
  git add "$i"
done

git commit -m "Updated $BRANCH branch of deployment repo to point to latest head of submodules"
git push origin $BRANCH

Para ejecutarlo, ejecutar

git-update-submodules.sh /path/to/base/repo BRANCH_NAME

Elaboración

Primero de todo, supongo que la rama con el nombre $RAMA (2ª argumento) existe en todos los repos. Siéntase libre de hacer esto aún más complejo.

Primero un par de secciones es la de algunos, la comprobación de que los argumentos están ahí. Luego me tire el padre de repo del material más reciente (yo prefiero usar --ff (avance rápido) cuando solo estoy haciendo tira. He de reajuste fuera, por cierto).

git checkout $BRANCH && git pull --ff origin $BRANCH

A continuación, algunos submódulo inicialización, puede ser necesario, si la nueva submódulos se han añadido o no se inicializó aún:

git submodule sync
git submodule init
git submodule update

Entonces puedo actualizar/tirar todos los submódulos:

git submodule foreach "(git checkout $BRANCH && git pull --ff origin $BRANCH && git push origin $BRANCH) || true"

Aviso un par de cosas: Primero de todo, yo soy el encadenamiento de algunos comandos usando git && - significado comando anterior debe ejecutar w/o error.

Después de un posible éxito de la extracción (si el nuevo material fue encontrado en el mando a distancia), tengo que hacer un esfuerzo para garantizar que una combinación posible de confirmación no se queda atrás en el cliente. De nuevo, sólo sucede si un tirón en realidad trajo cosas nuevas.

Por último, el final || true está asegurando que el guión sigue en errores. Para realizar este trabajo, todo en la iteración debe ser envuelto en las comillas dobles y el git-comandos están envueltos en parantheses (precedencia de operadores).

Mi parte favorita:

for i in $(git submodule foreach --quiet 'echo $path')
do
  echo "Adding $i to root repo"
  git add "$i"
done

Recorrer todos los submódulos - con --quiet, lo que elimina los 'Entrar MODULE_PATH' de salida. Utilizando 'echo $path' (debe ser en una sola cita), la ruta de acceso al submódulo se presenta por escrito a la salida.

Esta lista de relativa submódulo de los caminos es capturado en una matriz ($(...)) - finalmente recorrer en esto y git add $i para la actualización de los padres de repos.

Finalmente, una confirmación con un mensaje explicando que el padre de repos fue actualizado. Este commit será ignorado por defecto, si no se ha hecho nada. Pulse este origen, y listo.

Tengo un script que se ejecuta esta en una jenkins-trabajo, que se encadena a una automática programada después de la implementación, y funciona como un encanto.

Espero que esto le sea de ayuda a alguien.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X