Pregunta

Digamos que tengo cuatro proyectos llamados Core , A , B , Super . El árbol de dependencias es así:

Super ---> Core
       |-> A -> Core
       |-> B -> Core

Quiero que cada proyecto sea independiente, es decir, quiero poder retirar y compilar cada proyecto por sí mismo (cada uno con sus dependencias, por supuesto).

Pensé en asignar cada proyecto a un repositorio y luego referir dependencias con submódulos, pero veo los siguientes problemas con ese enfoque:

  1. Al revisar Super con todas sus dependencias, terminaría con tres copias de Core .
  2. Dado que los submódulos son completamente independientes, cada una de estas tres copias podría estar apuntando a diferentes revisiones de Core y eso sería un desastre.

Entonces ... ¿Me estoy perdiendo algo? ¿Entendí mal los submódulos git o los usé mal? ¿Hay alguna otra solución a este problema (aparte de recurrir a dependencias binarias)?

¿Fue útil?

Solución

Acaba de descubrir la falta de dependencias anuladas con los submódulos Git:

Si Super depende de Core, su dependencia de Core debería '' anular '' los que A y B tienen con Core.

La única forma de emular eso sería crear tu Superproyecto como lo hiciste,
y para eliminar el submódulo Core de A y B.
(lo que significa que Super depende ahora de A 'y B', A 'es A sin núcleo, B' es B sin núcleo)

Otros consejos

Los repositorios

git deben ser bastante atómicos en la forma en que cada repositorio es una entidad independiente para un propósito específico. ¿Cuál es el propósito del superproyecto además de combinar los proyectos A y B? Si no hay nada único (es decir, archivos que no están en A, B o Core), entonces es bastante redundante.

EDITAR: Debido a que los submódulos git son especialmente dolorosos en un lugar en el que trabajé, configuramos nuestro propio sistema de dependencia que rastrea repositorios dependientes a través de archivos de texto. Lo configuramos para que siempre rastree la cabeza de una rama, no una confirmación particular.

Pudimos configurar todos nuestros proyectos como si fueran parte del proyecto Super así:

Super
|-A
|-B
|-Core

Los proyectos se referenciarán entre sí utilizando rutas relativas, p. ../A/include.h . Verificar el repositorio A no funcionará, tendrías que crear otro `` super '' repositorio para trabajar solo en A:

AWorking
|-A
|-Core

EDITAR Otra razón para este comportamiento en git es que no puede rastrear cosas que están por encima del directorio raíz de repositorio (es decir, por encima de la carpeta que contiene la carpeta .git), que definitivamente sería necesario si desea que sus superproyectos y subproyectos hagan referencia a los mismos repositorios.

Creo que el problema aquí es una discrepancia entre el diseño de Git y el problema que está buscando resolver.

Git es bueno para hacer un seguimiento de los árboles. Las relaciones de dependencia entre proyectos pueden (y probablemente lo hacen) formar un gráfico. Un árbol es un gráfico, pero un gráfico no es necesariamente un árbol. Dado que su problema es cómo representar efectivamente un Gráfico, un Árbol no es la mejor herramienta para el trabajo.

Aquí hay un enfoque que podría funcionar:

Un proyecto git tiene un directorio .gitmodules donde registra " pistas " indicando de qué proyectos puede depender un commit, dónde se pueden encontrar y en qué ruta dentro del proyecto se espera que se inserten. ( http://osdir.com/ml/git/2009-04/msg00746. html )

Puede agregar un script que lea esta información de un conjunto de proyectos, asigne las sugerencias encontradas en el archivo .gitmodules de cada proyecto a las ubicaciones en el sistema de archivos donde esos proyectos se han colocado realmente, y luego agrega enlaces simbólicos de las rutas donde git espera ver submódulos a las ubicaciones reales del sistema de archivos de los respectivos proyectos.

Este enfoque utiliza enlaces simbólicos para salir del molde del árbol y construir un gráfico. Si registramos los enlaces directamente en los repositorios de git, tendríamos rutas relativas específicas a nuestra configuración local registradas en los proyectos individuales, y los proyectos no serían 'totalmente independientes' como usted quería. Por lo tanto, el script para construir dinámicamente los enlaces simbólicos.

Estoy pensando que este enfoque podría interferir con git de maneras indeseables, ya que hemos tomado caminos donde se espera encontrar una cosa, y poner otra cosa allí. Tal vez podríamos .gitignore las rutas de enlace simbólico. Pero ahora estamos escribiendo esos caminos dos veces y violando DRY. En este punto, también nos hemos alejado bastante de pretender usar submódulos. Podríamos registrar las dependencias en otro lugar de cada proyecto y dejar el archivo .gitmodules para las cosas que git espera. Así que crearemos nuestro propio archivo, por ejemplo, .dependencies, y cada proyecto puede indicar sus dependencias allí. Nuestro script buscará allí y luego irá y construirá sus enlaces simbólicos.

Hmm, creo que acabo de describir un sistema de gestión de paquetes ad-hoc, con su propio formato de paquete ligero :)

La sugerencia de

megamic me parece un buen uso de los submódulos git. Solo estamos tratando de hacer un seguimiento de un conjunto aquí en lugar de un gráfico, y un conjunto encaja fácilmente en un árbol. Un árbol de un nivel de profundidad es esencialmente un nodo primario y un conjunto de nodos secundarios.

Como señaló, eso no resuelve completamente el problema planteado en su pregunta. Podemos dividir dos tipos distintos de "esto funciona con eso" información que probablemente nos interese:   1. Una declaración de una versión de un proyecto (presumiblemente por el autor del proyecto) que dice "Necesito la versión X del proyecto Y".   2. Una declaración utilizada por su propia configuración de compilación que dice "He probado con éxito todo nuestro sistema utilizando este conjunto de versiones de proyecto"

la respuesta de megamic se resolvió (2) pero para (1) todavía queremos que los proyectos nos digan cuáles son sus dependencias. Entonces podemos usar la información de (1) para calcular esos conjuntos de versiones que terminaremos grabando como (2). Este es un problema lo suficientemente complejo como para garantizar su propia herramienta, que nos lleva de vuelta a los sistemas de gestión de paquetes :)

Hasta donde yo sé, la mayoría de las buenas herramientas de administración de paquetes están hechas para usuarios de un idioma o sistema operativo específico. Ver Bundler para paquetes 'gem' en el mundo ruby ??y apto para paquetes '.deb' en el mundo Debian.

Si alguien sabe de una buena solución neutral para el lenguaje y para el sistema operativo que sea adecuada para 'polyglot' ( http://blog.heroku.com/archives/2011/8/3/polyglot_platform/ ) proyectos de programación, estaría muy interesado

Creo que puede administrar la coherencia de esta manera: defina una " referencia " rama o serie de etiqueta con el mismo nombre (s) en todos sus " Core " bibliotecas (nota: solo hay una biblioteca '' Core '' en su ejemplo). Luego, indique a los desarrolladores de subproyectos (A, B, ...) que actualicen regularmente a la versión de referencia de "Core". tan pronto como puedan.

Antes de ejecutar una compilación, compruebe fácilmente que " Core (s) " se usa constantemente en A, B, C, ... ejecutando estos tres comandos en un proceso de limpieza de nivel superior, limpio, recursivo, "Super",

# 1.  Switch to the reference version (= "Force" consistency where need be)
git submodule foreach --recursive 'git checkout [origin/]reference || true'

# 2a. Show which inconsistencies you just forced; terse output
git status -s; git submodule foreach --recursive git status -s 2>/dev/null

# 2b. Same but verbose output
git submodule; git submodule foreach --recursive git submodule

# 3. Switch back to versions individually defined by sub-projects 
git submodule update --recursive

La salida de " Terse " el comando 2a anterior resalta qué subproyecto (s) no están utilizando la "referencia" versión de Core.

Puede ampliar fácilmente el enfoque para mostrar diferencias, forzar actualizaciones o hacer cualquier otra cosa que desee.

Una pequeña tarea de utilidad que convierte submódulos compartidos en clones utilizando enlaces duros podría funcionar.

Puede leer mi solución completa aquí: https://stackoverflow.com/a/10265084/84283

No intentaría asignar un árbol de dependencias con submódulos, por las razones que ya ha descubierto.

Los submódulos rastrean una revisión dada de una rama dada, por lo que son útiles para proporcionar una instantánea de un conjunto consistente de módulos.

Entonces, si su proyecto requirió un cierto conjunto de versiones de diferentes módulos para ser rastreados como una unidad, puede agruparlos como submódulos. Luego puede etiquetar diferentes conjuntos de módulos en diferentes versiones, para dar un historial del proyecto, donde cada etiqueta muestra qué versiones de qué módulos eran compatibles en un momento determinado.

 tags/
     release1/ 
           |-> A@1.0
           |-> B@1.1
           |-> C@1.2
     release2/
           |-> A@2.0
           |-> B@1.3
           |-> C@1.5

Al menos así es como los entiendo, aunque como la mayoría de las cosas con Git, probablemente hay mucho más que eso. En términos de gestión de dependencias, todo lo que puedo decir es encontrar otra forma, no es para lo que Git con o sin submódulos fue diseñado, según tengo entendido.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top