2009-09-14 17 views
43

Digamos que tienen cuatro proyectos mencionados Core, Un, B, Súper. El árbol de dependencias es así:submódulos de Git y dependencias anidadas

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

Quiero que cada proyecto sea independiente, es decir, quiero ser capaz de salida y compilar cada proyecto por sí mismo (cada uno con sus dependencias, por supuesto,)

pensé en la cartografía de cada proyecto en un repositorio y luego en referencia dependencias de cartuchos, pero veo los siguientes problemas con este enfoque:

  1. Al salir Súper con todas sus dependencias, que había terminar 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.

Así que ... ¿Me estoy perdiendo algo? ¿Entendí mal los submódulos de Git o los utilicé mal? ¿Hay alguna otra solución a este problema (que no sea recurrir a dependencias binarias)?

Respuesta

12

Usted acaba de descubrir la falta de dependencias que se modifique con submódulos de Git:

Si Súper depende de Core, su dependencia del núcleo debe "override" los A y B tienen con el sistema central.

La única manera de emular esa sería la creación de su proyecto Súper la manera que lo hizo,
y para eliminar el Núcleo submódulo de A y B.
(es decir, el Super depende ahora de A' y B ', A' siendo A sin Core, B 'siendo B sin Core)

7

git repositories 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: Dado que los submódulos de git son especialmente dolorosos en un lugar en el que trabajé, creamos nuestro propio sistema de dependencia que rastrea los repositorios dependientes a través de archivos de texto. Lo configuramos para que siempre rastree la cabeza de una rama, no un compromiso en particular.

Nos eran capaces de establecer todos nuestros proyectos como si fueran una parte de todo el proyecto Super así:

Super 
|-A 
|-B 
|-Core 

Los proyectos se referirán entre sí mediante rutas relativas, por ejemplo, ../A/include.h. El registro de salida de recompra A no va a funcionar, usted tendría que crear otro repo "super" para trabajar sólo en A:

AWorking 
|-A 
|-Core 

EDITAR Otra razón para este comportamiento en Git es que no se puede realizar un seguimiento de las cosas que están encima del directorio de repositorio raíz (es decir, encima de la carpeta que contiene la carpeta .git), lo cual sería definitivamente necesario si desea que sus superproyectos y subproyectos se refieran a los mismos repositorios.

+0

Super es un proyecto en sí mismo. No asuma que no tiene contenido solo porque lo llamé Super. –

+1

Pero quiero que cada proyecto sea independiente. Y me gusta que los submódulos de git se fijen a una confirmación particular en lugar de seguirlos como svn externos, por lo que un cambio en el núcleo no rompería inmediatamente A, B y Súper. –

+1

Si rastreas ramas o comprometes SHA es completamente tu decisión. Pero la mejor respuesta para su problema es que no es posible tener tanto la opción de proyecto independiente como la de super proyecto. En la práctica, me pareció que tener un superproyecto para cada subproyecto no es tan importante. –

0

No trataría de mapear 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 determinada, por lo que son útiles para proporcionar una instantánea de un conjunto coherente de módulos.

Por lo tanto, si su proyecto requiere un determinado conjunto de versiones de diferentes módulos para ser rastreados como una unidad, puede agruparlos como submódulos.A continuación, puede etiquetar diferentes conjuntos de módulos en diferentes versiones, para proporcionar un historial del proyecto, donde cada etiqueta muestra qué versiones de qué módulos son compatibles en un momento determinado.

tags/ 
    release1/ 
      |-> [email protected] 
      |-> [email protected] 
      |-> [email protected] 
    release2/ 
      |-> [email protected] 
      |-> [email protected] 
      |-> [email protected] 

Al menos que la forma en que los entiendo, aunque al igual que la mayoría de las cosas con Git, es probable que haya mucho más que eso. En términos de administración de dependencias, todo lo que puedo decir es encontrar otra manera, no es para lo que se diseñó Git con o sin submódulos, tal como lo entiendo.

+0

Ok ... pero creo que esto resuelve un problema diferente ... no el que estoy preguntando. –

6

Creo que el problema aquí es un desajuste entre el diseño de Git y el problema que está tratando de resolver.

Git es bueno para hacer el seguimiento de Árboles. Las relaciones de dependencia entre proyectos pueden (y probablemente lo hagan) 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í es un enfoque que podría funcionar:

Un proyecto Git tiene un directorio .gitmodules donde registra "sugerencias" que indica que proyecta un commit puede depender, en los que se pueden encontrar, y qué camino dentro del proyecto se espera que sean insertados en. (http://osdir.com/ml/git/2009-04/msg00746.html)

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

Este enfoque usa enlaces simbólicos para salir del molde Árbol y construir un Gráfico. Si grabamos los enlaces directamente en los repositorios git, tendríamos rutas relativas específicas para nuestra configuración local registradas en los proyectos individuales, y los proyectos no serían "totalmente independientes" como usted quería. Por lo tanto, la secuencia de comandos para construir dinámicamente los enlaces simbólicos.

Estoy pensando que este enfoque podría interferir con git de formas no deseadas, ya que hemos tomado caminos donde espera encontrar una cosa, y ponemos algo más 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 en cada proyecto, y dejar el archivo .gitmodules para las cosas que git espera. Así que crearemos nuestro propio archivo, digamos, .dependencias, y cada proyecto puede indicar sus dependencias allí. Nuestro script se verá allí y luego irá y construirá sus enlaces simbólicos.

Hmm, creo que puede haber simplemente se describe un sistema de gestión de paquetes ad hoc, con su propio formato de paquete ligero :) sugerencia

de megamic parece un buen uso de los submódulos git para mí.Solo tratamos 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 padre y un Conjunto de nodos secundarios.

Como ha señalado, eso no resuelve por completo el problema planteado en su pregunta. Podemos dividir dos tipos distintos de información de "esto funciona con eso" en la que probablemente estamos interesados: 1. Una declaración de una versión de un proyecto (presumiblemente del 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 diciendo "He probado con éxito todo nuestro sistema usando este conjunto de versiones de proyecto"

respuesta de megamic resuelto (2) pero para (1) todavía queremos proyectos que nos digan cuáles son sus dependencias Entonces podemos usar la información de (1) para calcular los conjuntos de versiones que terminaremos registrando como (2). Este es un problema bastante complejo para garantizar su propia herramienta, que nos devuelve a los sistemas de administración de paquetes :)

Por lo que 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 de 'gemas' en el mundo de ruby ​​y apto para paquetes '.deb' en el mundo de Debian.

Si alguien sabe de una buena solución de lenguaje neutro, OS-neutro a esto que se adapta bien a 'políglota' (http://blog.heroku.com/archives/2011/8/3/polyglot_platform/) la programación de proyectos, estaría muy interesado! Debería publicar eso como una pregunta.

+1

+1 Dado que su problema es cómo representar efectivamente un gráfico, un árbol no es la mejor herramienta para el trabajo. –

2

Creo que puede gestionar la coherencia de esta manera: defina una rama de "referencia" o una serie de etiquetas con el mismo nombre en todas sus bibliotecas "Core" (nota: solo hay una biblioteca "Core" en su ejemplo). A continuación, solicite 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 utiliza sistemáticamente en A, B, C, ... ejecutando estos tres comandos en un proceso limpio, recursivo, "Super", de alto nivel :

# 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 

el "Conciso de salida" comando 2a anterior destaca que sub-proyecto (s) no están utilizando la "referencia" versión de Core.

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

Cuestiones relacionadas