2010-08-28 9 views
46

He dos o más proyectos (llamémosles ProjectFoo y ProjectBar) que tienen alguna código común que puse en un submódulo.Git se comprometen a submódulo común (rama principal)

Mi opinión es que si me confirmó cambios en un submódulo de dentro ProjectFoo que va a ser en una cabeza separada que sólo los ProjectFoo clones pueden ver:

(master) $ cd ProjectFooBarCommoneSubmodule/ 
(master) $ git commit -am "Common code fix." 
(56f21fb0...) $ git push 
Everything up-to-date 

Eso es probablemente porque el master sucursal no ha cambiado Probablemente podría hacer algo como git checkout master && git merge Everything up-to-date, pero eso parece bastante feo. Puede ser un git reset --hard master haría lo mismo, pero parece incluso más feo.

¿Cómo tener un código común compartido por proyecto, actualizado desde dentro de aquellos proyectos que lo usen? En otras palabras, el compromiso con ese submódulo debería actualizar todos los repositorios (repositorios , no solo los clones) que usan este mismo submódulo.

---- ---- EDITAR

Visiblemente mi repositorio desprotegido fue desordenado y roto. Debería haber trabajado desde el principio como que (en ProjectFoo en este ejemplo):

(master) $ cd ProjectFooBarCommoneSubmodule/ 
(master) $ git commit -am "Common code fix." 
(master) $ git push 
.... 
    fbfdd71..0acce63 master -> master 
(master) $ cd .. 
(master) $ git add ProjectFooBarCommoneSubmodule 
(master) $ git commit -m "Submodule update." 

luego a que ese cambio de en otros proyectos, como ProjectBar:

(master) $ cd ProjectFooBarCommoneSubmodule/ 
(master) $ git pull 

Would actualizar al último código común. Es posible que se requiera git checkout master si está en una cabeza separada.

Respuesta

60

respuesta corta:

cd ProjectFooBarCommoneSubmodule 
git checkout master 
<Do your editing> 
git commit --all -m "Lots of fixes" 
git push submodule_origin master 
cd .. 

git add ProjectFooBarCommoneSubmodule 
git commit -m "Bumped up the revision of ProjectFooBarCommoneSubmodule" 
git push origin master 

el más largo:

submódulos de Git son un mecanismo de dependencia, donde el proyecto principal (por ejemplo A) define una revisión especificado en un subproyecto (dicen B), que se usará en la construcción del proyecto A. Para que la herramienta sea útil, el comportamiento debe ser predecible desde el punto de vista de A: s. Las dependencias no pueden cambiar, a menos que alguien decida incorporar el cambio al proyecto A. Podrían ocurrir todo tipo de cosas desagradables, fueron los cambios del proyecto B: s importados automáticamente, de los cuales los errores de compilación son probablemente los mejores, ya que A notaría los fallos inmediatamente. Esta es la razón por la cual la cabeza B: s se mantiene en estado separado.

El estado de B se almacena en A (marca git submodule status), y un cambio de revisión debe hacerse y confirmarse en A, para que tenga algún efecto. Esto es lo que sucede en el ejemplo anterior, A cambia el número de revisión almacenado en el repositorio y aumenta la versión a la última. El proceso tendrá que repetirse también en el otro repositorio principal, por lo que no habrá ningún interruptor automático "maestro de uso" AFAIK.

BTW. El Git book chapter on submodules y el submodule man page contienen mucha información útil sobre los submódulos, como el uso normal y las trampas típicas. Vale la pena echarle un vistazo.


EDIT: Voy a tratar de explicar esto mejor

he tomado la libertad de crear proyectos de ejemplo en my github account. Los commits no tienen sentido y contienen basura, pero la configuración debería estar bien. Por favor, échale un vistazo para seguir.

Tanto ProjectFoo como ProjectBar comparten el código en el submódulo común.

ProjectFooBarCommoneSubmodule: master es 6850e4e4c1fac49de398

En ProjectFoo:

git submodule status 

-6850e4e4c1fac49de39890703f21486ca04b87a0 común

En ProjectBar:

git submodule status 

-6850e4e4c1fac49de39890703f21486ca04b87a0 común

Por lo tanto, ambos apuntan a la misma revisión, ¿no? El truco aquí es ver que ProjectFoo y ProjectBar apuntan a la revisión (6850e4e4c1fac49de39890703f21486ca04b87a0) no a la rama (principal), aunque son lo mismo. El primero es una cabeza separada, y el otro una rama nombrada.

Si quiere arreglar algo en ProjectFooBarCommoneSubmodule, puede ir al subdirector, p. ProjectFoo y elegir la rama en lugar de la revisión:

git checkout master 
<Do your coding and pushing here> 

Luego entra un directorio arriba, y comprobar el estado de submódulo git. Debería decirte que ahora estás fuera de sincronización. Por ejemplo

git submodule status 

+ e24bd2bf45d52171a63b67ac05cd4be0ac965f60 común (cabezas/master-1-ge24bd2b)

Ahora usted puede hacer un git add, para establecer la referencia a este particular comprometerse (ge24bd ...), hacer un commit y después de esto, la referencia del submódulo apunta a esta revisión, que también es maestra en ProjectFooBarCommoneSubmodule.

Ahora debe actualizar la referencia en ProjectBar también. Ir a ProjectBar/común, y hacer git fetch origen (esto es una combinación de avance rápido), hacer

git checkout master 
cd .. 
git add common 
git commit -m "Bumped up the revision" 
git push origin master # to publish the revision bump to everybody else 

Por lo tanto, al igual que con cualquier repositorio git, que no es necesario trabajar en una cabeza separada. Puede trabajar en el maestro o crear una rama con nombre. De cualquier manera, asegúrese de que el flujo ascendente contenga los cambios de ProjectFooBarCommoneSubmodule, o dividirá ProjectFoo y ProjectBar, si hacen referencia a algo que no existe.Espero que esto lo explicó mejor

+0

Gracias, vi ese capítulo. Tristemente, no encontré una respuesta clara a mi pregunta. Usted dice que no hay un maestro de uso automático, entonces, ¿qué ocurre si se actualiza un subproyecto común, digamos una biblioteca? ¿No es una actualización de 'git submódulo' va a actualizar todos los proyectos que dependen de esa biblioteca? Me gustaría hacer lo mismo, pero actualizar esa biblioteca directamente desde cualquiera de mis proyectos principales. Si eso no es posible, ¿cuál sería la alternativa? – Wernight

+0

Los repositorios de Git no contienen información sobre quién los ha clonado. Es por eso que es imposible enviar cambios a todos los clones. Haciendo las cosas simples, creo que estás esperando algo así como enlaces simbólicos, por lo que cualquier cosa se propagaría de inmediato, mientras que los clones son más como "tar, gzip, copy, unzip". La clave probablemente sea publicar el número de revisión modificado en Foo y Bar. Cualquier persona que busque cambios verá el número de revisión modificado la próxima vez. Cualquier cosa mejor que eso, diría que no. Estaría contento de haber demostrado estar equivocado en esto, sin embargo. –

+0

Sure clones tiene que hacer una actualización o extracción manualmente. Mi pregunta es, ¿cómo? Dos proyectos, no clones, que comparten un código común en un submódulo de Git. ¿Hay alguna otra opción que ProjectFoo asigna submódulo a la cabeza separada, entonces ProjectBar (NO un clon) combina los cambios (si eso es posible, no sé dónde están almacenados esos cambios). – Wernight

2

Por submodule: git push origin HEAD:master

0

Si quieres cometer y empujar todos los submódulos a la vez hacer: git submodule foreach 'git commit -a' ; git submodule foreach 'git push --all' ; git commit -a && \ git push --all --recurse-submodules=on-demand

0

Para combinar cambiado de cabeza separada en maestro, ejecute:

git rebase HEAD master 

maestro entonces checkout (uso -f para la fuerza):

git checkout master 

Si tiene que tratar varios submódulos, use: git submodule foreach, p. Ej.

git submodule foreach git pull origin master -r 
0

acabo de hacer:

git submodule foreach git push -u origin master

Cuestiones relacionadas