2008-10-21 11 views
108

En primer lugar, sé de esto: How would you organize a Subversion repository for in house software projects? A continuación, la pregunta real: Mi equipo está reestructurando nuestro repositorio y estoy buscando consejos sobre cómo organizarlo. (SVN en este caso). Esto es lo que se nos ocurrió. Tenemos un repositorio, múltiples proyectos y SVN múltiple: de externos referencias cruzadas¿Cómo se organiza el repositorio de control de versiones?

\commonTools /*tools used in all projects. Referenced in each project with svn:externals*/ 
    \NUnit.v2.4.8 
    \NCover.v.1.5.8 
    \<other similar tools> 
\commonFiles /*settings strong name keys etc.*/ 
    \ReSharper.settings 
    \VisualStudio.settings 
\trash /*each member of the team has trash for samples, experiments etc*/ 
    \user1 
    \user2 
\projects 
    \Solution1 /*Single actual project (Visual Studio Solution)*/ 
     \trunk 
     \src 
      \Project1 /*Each sub-project resulting in single .dll or .exe*/ 
      \Project2 
     \lib 
     \tools 
     \tests 
     \Solution1.sln 
     \tags 
     \branches 
    \Solution2 
     \trunk 
     \src 
      \Project3 /*Each sub-project resulting in single .dll or .exe*/ 
      \Project1 /*Project1 from Solution1 references with svn:externals*/ 
     \lib 
     \tools 
     \tests 
     \Solution2.sln 
     \tags 
     \branches 

Para borrar el vocabulario: Solución significa solo producto, es un proyecto de Visual Studio (que se traduce en una sola .dll o .exe sola)

Así es como planeamos diseñar el repositorio. El problema principal es que tenemos múltiples soluciones, pero queremos compartir proyectos entre soluciones. Pensamos que realmente no tiene sentido mover esos proyectos compartidos a sus propias soluciones, y en su lugar, decidimos usar svn: external para compartir proyectos entre soluciones. También queremos mantener un conjunto común de herramientas y bibliotecas de terceros en un lugar del repositorio, y hacer referencia a ellas en cada solución con svn: external.

¿Qué opinas sobre este diseño? Especialmente sobre el uso de svn: externals. No es una solución ideal, pero considerando todos los pros y los contras, es lo mejor que se nos ocurre. ¿Como lo harias?

+0

¿Seguro que quieres decir "thrash"? ¿O más bien "basura"? – ssc

Respuesta

90

Si sigues mis recomendaciones a continuación (tengo desde hace años), usted será capaz de:

- poner a cada proyecto en cualquier lugar de control de origen, siempre y cuando se preserve la estructura del directorio raíz del proyecto de abajo

- generar cada proyecto en cualquier lugar en cualquier máquina, con un riesgo mínimo y un mínimo de preparación

- generar cada proyecto totalmente independiente, siempre y cuando usted tiene acceso a sus dependencias binarias ("biblioteca" local y directorios de "salida")

- construir y trabajar con cualquier combinación de proyectos, ya que son independientes

- construir y trabajar con múltiples copias/versiones de un mismo proyecto, ya que son independientes

- evitar llenar su fuente repositorio de control con los archivos o bibliotecas

recomiendo generados (aquí está la carne):

  1. definir cada proyecto para producir un único resultado principal, como por ejemplo un .DLL, .EXE, o. JAR (predeterminado con Visual Studio).

  2. Estructura cada proyecto como un árbol de directorios con una sola raíz.

  3. Cree un script de compilación automatizado para cada proyecto en su directorio raíz que lo compilará desde cero, sin dependencias en un IDE (pero no impida que se construya en el IDE, si es factible).

  4. Considere Nant para proyectos .NET en Windows, o algo similar en base a su sistema operativo, plataforma de destino, etc.

  5. hacen referencia todos los scripts de generación de proyecto sus dependencias (3 ª parte) externos de una sola locales directorio "biblioteca" compartido, con cada uno de esos binarios TOTALMENTE identificado por versión: %DirLibraryRoot%\ComponentA-1.2.3.4.dll, %DirLibraryRoot%\ComponentB-5.6.7.8.dll.

  6. Haga que cada script de construcción de proyecto publique el entregable principal en un solo directorio de "salida" compartido local: %DirOutputRoot%\ProjectA-9.10.11.12.dll, %DirOutputRoot%\ProjectB-13.14.15.16.exe.

  7. Haga que cada script de compilación de proyecto haga referencia a sus dependencias a través de rutas absolutas configurables y totalmente versionadas (consulte más arriba) en los directorios "biblioteca" y "salida", Y NO EN DONDE MÁS.

  8. NUNCA deje que un proyecto haga referencia directamente a otro proyecto o cualquiera de sus contenidos, solo permita referencias a los entregables primarios en el directorio de "salida" (vea arriba).

  9. Haga que cada referencia de script de compilación de proyecto sea necesaria mediante una ruta absoluta configurable y completamente versionada: %DirToolRoot%\ToolA\1.2.3.4, %DirToolRoot%\ToolB\5.6.7.8.

  10. Haga que cada fuente de referencia de script de compilación de proyecto tenga una ruta absoluta en relación con el directorio raíz del proyecto: ${project.base.dir}/src, ${project.base.dir}/tst (la sintaxis varía según la herramienta de compilación).

  11. requieren siempre una escritura de la estructura del proyecto para hacer referencia CADA archivo o directorio a través de una ruta absoluta, configurable (con raíz en un directorio especificado por una variable configurable): ${project.base.dir}/some/dirs o ${env.Variable}/other/dir.

  12. Nunca permita que un script de construcción del proyecto para hacer referencia a cualquier cosa con una ruta relativa como .\some\dirs\here o ..\some\more\dirs, utilice siempre rutas absolutas.

  13. NUNCA permita que un script de compilación de proyecto haga referencia a ALGUNO usando una ruta absoluta que no tenga un directorio raíz configurable, como C:\some\dirs\here o \\server\share\more\stuff\there.

  14. Para cada directorio raíz configurable al que hace referencia un script de compilación de proyecto, defina una variable de entorno que se utilizará para esas referencias.

  15. Intente minimizar el número de variables de entorno que debe crear para configurar cada máquina.

  16. En cada máquina, cree un script de shell que defina las variables de entorno necesarias, que son específicas de esa máquina (y posiblemente específicas de ese usuario, si corresponde).

  17. NO ponga la secuencia de comandos de shell de configuración específica de la máquina en el control de fuente; en su lugar, para cada proyecto, envíe una copia del script en el directorio raíz del proyecto como una plantilla.

  18. REQUIERE cada script de construcción del proyecto para verificar cada una de sus variables de entorno, y cancele con un mensaje significativo si no están definidas.

  19. REQUIERE cada script de compilación de proyecto para verificar cada uno de sus ejecutables de herramienta de compilación dependientes, archivos de biblioteca externa y archivos entregables de proyecto dependientes, y cancele con un mensaje significativo si esos archivos no existen.

  20. resistir la tentación de cometer cualquier archivo generado en el control de la fuente - no entregables del proyecto, sin fuente generado, sin documentos generados, etc.

  21. Si utiliza un IDE, generar archivos de cualquier proyecto de control puede , y no los comprometan con el control de origen (esto incluye los archivos de proyecto de Visual Studio).

  22. Establezca un servidor con una copia oficial de todas las bibliotecas y herramientas externas, para ser copiado/instalado en estaciones de trabajo de desarrollador y máquinas de construcción. Haga una copia de seguridad, junto con su repositorio de control de origen.

  23. Establezca un servidor de integración continua (máquina de compilación) sin herramientas de desarrollo en absoluto.

  24. Considere una herramienta para gestionar sus bibliotecas externas y entregables, como Ivy (utilizado con Ant).

  25. NO use Maven - inicialmente lo hará feliz, y finalmente lo hará llorar.

Tenga en cuenta que nada de esto es específico de la subversión, y la mayoría de que es similar para proyectos dirigidos a cualquier sistema operativo, hardware, plataforma, lenguaje, etc. Hice uso de un poco de OS- y herramienta específica sintaxis, pero solo a modo de ilustración: confío en que lo traducirás a tu sistema operativo o herramienta de elección.

Nota adicional sobre las soluciones de Visual Studio: ¡no las ponga en control de fuente! Con este enfoque, no los necesita en absoluto o puede generarlos (al igual que los archivos de proyecto de Visual Studio). Sin embargo, considero que es mejor dejar los archivos de la solución a desarrolladores individuales para que los creen/usen como mejor les parezcan (pero no se verifiquen en el control de la fuente). Guardo un archivo Rob.sln en mi estación de trabajo desde el cual hago referencia a mi (s) proyecto (s) actual (es). Como mis proyectos son independientes, puedo agregar/eliminar proyectos a voluntad (eso significa que no hay referencias de dependencia basadas en proyectos).

No utilice Subversion externos (o similares en otras herramientas), son un antipatrón y, por lo tanto, innecesarios.

Cuando implemente la integración continua, o incluso cuando solo desee automatizar el proceso de lanzamiento, cree un script para él. Cree un único script de shell que: tome los parámetros del nombre del proyecto (como figura en el repositorio) y el nombre de la etiqueta, cree un directorio temporal dentro de un directorio raíz configurable, compruebe el origen del nombre del proyecto y el nombre de la etiqueta (construyendo el URL apropiada en el caso de Subversion) a ese directorio temporal, realiza una compilación limpia que ejecuta pruebas y empaqueta el entregable. Este script de shell debería funcionar en cualquier proyecto y se debe verificar en el control de código fuente como parte de su proyecto de "herramientas de compilación". Su servidor de integración continua puede usar este script como base para la creación de proyectos, o incluso podría proporcionarlo (pero aún puede querer el suyo).

@VonC: NO querrás trabajar en todo momento con "ant.jar" en lugar de "ant-abcdjar" después de quemarte cuando se rompa tu script de compilación porque sin saberlo lo ejecutaste con una versión incompatible de Ant .Esto es particularmente común entre Ant 1.6.5 y 1.7.0. Generalizando, SIEMPRE desea saber qué versión específica de CADA componente se está utilizando, incluida su plataforma (Java A.B.C.D.) y su herramienta de compilación (Ant E.F.G.H.). De lo contrario, eventualmente encontrará un error y su primer gran problema será rastrear qué versiones de sus diversos componentes están involucradas. Simplemente es mejor resolver ese problema por adelantado.

+6

¡Tantos puntos para criticar ... basta decir que esto * no * es una receta universal! Los puntos 5 y 6 en particular están muy equivocados cuando el proyecto es grande y el número de terceros es importante: usted quiere trabajar en todo momento con 'ant.jar', no 'ant1.5.4.jar', o producto myProduct .exe, no 1.3.exe – VonC

+5

Aún así, +1 para muchos otros puntos que está haciendo que son válidos y habla muy bien por su amplia experiencia en el tema. – VonC

+3

Me encantaría escuchar e interactuar con sus críticas; cada punto se basa en resolver malas experiencias con proyectos grandes. Por ejemplo, abordar el problema de qué versiones están representadas por Xxx.jar e Yyy.exe, especialmente cuando se hace referencia a una docena de copias literalmente. –

3

Creo que Pragmatic Version Control using Subversion tiene todo lo que necesita para organizar su repositorio.

+0

Ahora en una 2da edición: http://is.gd/Eo4 – balexandre

+6

@bal Por favor, no use los servicios de reducción de URL. Es * mucho * mejor decir "Ahora en su segunda edición: [Pragmatic Version Control using Subversion] (http://www.pragprog.com/titles/svn2/pragmatic-version-control-using-subversion)" – meagar

3

Hemos configurado el nuestro para que coincida casi exactamente con lo que ha publicado. Utilizamos la forma general:

\Project1 
    \Development (for active dev - what you've called "Trunk", containing everything about a project) 
    \Branches (For older, still-evolving supported branches of the code) 
     \Version1 
     \Version1.1 
     \Version2 
    \Documentation (For any accompanying documents that aren't version-specific 

Aunque supongo que no tan completa como su ejemplo, ha funcionado bien para nosotros y nos permite mantener las cosas separadas. También me gusta la idea de que cada usuario tenga una carpeta "Thrash"; actualmente, esos tipos de proyectos no terminan en el control de Source, y siempre he pensado que deberían hacerlo.

+3

I Me sorprende que tengas un directorio separado para documentos que no cambian entre versiones ... ¡Nunca tuve el placer de trabajar en un producto así! :) – ARKBAN

0

Tengo un diseño similar, pero mi tronco, ramas, etiquetas todo el camino en la parte superior. Entonces:/trunk/main,/trunk/utils,/branches/release /, etc.

Esto terminó siendo muy útil cuando queríamos probar otros sistemas de control de versiones porque muchas de las herramientas de traducción funcionaban mejor con el diseño básico SVN de libros de texto.

0

Creo que la principal desventaja de la estructura propuesta es que los proyectos compartidos solo se versionarán con la primera solución a la que se agregaron (a menos que svn: externals sea más elegante de lo que imagino). Por ejemplo, cuando crea una rama para la primera versión de Solution2, Project1 no se ramificará, ya que vive en Solution1. Si necesita construir desde esa rama en un momento posterior (versión QFE), usará la última versión de Project1 en lugar de la versión de Project1 en el momento de la sucursal.

Por esta razón, puede ser ventajoso para poner los proyectos compartidos en una o más soluciones compartidas (y por tanto directorios de nivel superior en su estructura) y luego se ramifican con cada versión de cualquier solución.

+0

Tiene razón hasta cierto punto. Pero podemos actualizar la referencia si queremos. Y poner Proyectos compartidos en su propia Solución tampoco tiene mucho sentido. Aunque me encantaría encontrar una solución mejor que svn: externos por todas partes. –

+0

¿Qué quiere decir con "actualizar la referencia si queremos"? No veo cómo podría ramificar Project1 (lo cual parece deseable cada vez que ramifique Solution2) sin ramificar Solution1. –

+0

Consulte mi respuesta detallada, particularmente para NO poner soluciones de Visual Studio en control de código fuente. –

1

¿Por qué tener todo en un repositorio? ¿Por qué no tener un repositorio separado para cada proyecto (me refiero a "Solución")?

Bueno, al menos yo he usado el enfoque de un proyecto por repositorio. Tu estructura de repositorio me parece demasiado complicada.

¿Y cuántos proyectos planea poner en este gran repositorio? 2? 3? 10? 100?

¿Y qué haces cuando cancelas el desarrollo de un proyecto? Simplemente elimínelo del árbol de repositorio para que sea difícil de encontrar en el futuro. ¿O dejarlo por siempre? ¿O cuando quieres mover un proyecto a otro servidor por completo?

¿Y el desorden de todos esos números de versión? Los números de versión de un proyecto van como 2, 10, 11, mientras que el otro va como 1, 3, 4, 5, 6, 7, 8, 9, 12 ...

Quizás soy tonto, pero Me gusta un proyecto por repositorio.

+0

1. Un repositorio es una política de la compañía, no puede cambiar eso. 2. Tendremos alrededor de una docena de Soluciones. 3. ¿Por números de versión te refieres a revisiones? Eso no es un problema para nosotros. –

+0

Una buena estructura de proyecto debe ser ajena al resto de la estructura del repositorio, particularmente con respecto a uno o varios repositorios. Por favor mira mi respuesta detallada. –

+1

Tenga en cuenta que tener múltiples repositorios en muchas (¿la mayoría?) Herramientas de control de origen puede ser MUY costoso, como cuando se implementa la seguridad. –

0

Para añadir a la cuestión ruta relativa:

No estoy seguro de que es un problema:
Sólo la caja Solución 1/tronco bajo el directorio llamado "Solución 1", lo mismo para Solución 2: el objetivo de 'directorios' en realidad representando ramas es no ser visible una vez importado en un espacio de trabajo. Por lo tanto, las rutas relativas son posibles entre 'Solution1' (en realidad 'Solution1/trunk') y 'Solution2' (Solution2/trunk).

+0

Esto se rompería muy fácilmente, por favor vea mi respuesta detallada. –

0

RE: la ruta relativa y emisión de archivos compartidos -

parece que este es SVN específica, pero eso no es un problema. Otra persona ya mencionó repositorios separados y esa es probablemente la mejor solución que puedo pensar en el caso en que tenga proyectos diferentes que se refieran a otros proyectos arbitrarios. En el caso de que no tenga archivos compartidos, la solución de OP (así como muchos otros) funcionará bien.

Todavía estamos trabajando en esto y tengo 3 esfuerzos diferentes (clientes diferentes) que tengo que resolver en este momento desde que asumí la configuración de control de versión inexistente o deficiente.

+0

Tener proyectos que hagan referencia a otros proyectos crea una pesadilla de mantenimiento porque las dependencias crecen exponencialmente y las referencias son MUY frágiles. Por favor mira mi respuesta detallada. –

Cuestiones relacionadas