Primero, sé esto: ¿Cómo organizarías un repositorio de Subversion para proyectos de software internos? A continuación, la pregunta real: mi equipo está reestructurando nuestro repositorio y estoy buscando sugerencias sobre cómo organizarlo. (SVN en este caso). Esto es lo que se nos ocurrió. Tenemos un repositorio, múltiples proyectos y múltiples svn: referencias cruzadas externas
\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 producto único, Project es un proyecto de Visual Studio (que da como resultado un solo .dll o un solo .exe)
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: externals 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 ellos en cada Solución con svn: externals.
¿Qué opinas de 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?
fuente
Respuestas:
Si sigue mis recomendaciones a continuación (las he hecho durante años), podrá:
- coloque cada proyecto en cualquier lugar del control de código fuente, siempre que conserve la estructura desde el directorio raíz del proyecto hacia abajo
- construya cada proyecto en cualquier lugar de cualquier máquina, con un riesgo mínimo y una preparación mínima
- construya cada proyecto de forma completamente independiente, siempre que tenga 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 solo proyecto, ya que son independientes
- evite saturar su repositorio de control de fuente con archivos o bibliotecas generados
Recomiendo (aquí está la carne):
Defina cada proyecto para producir una única entrega principal, como .DLL, .EXE o .JAR (predeterminado con Visual Studio).
Estructure cada proyecto como un árbol de directorios con una sola raíz.
Cree un script de compilación automatizado para cada proyecto en su directorio raíz que lo compile desde cero, SIN dependencias en un IDE (pero no impida que se compile en el IDE, si es posible).
Considere nAnt para proyectos .NET en Windows, o algo similar según su sistema operativo, plataforma de destino, etc.
Haga que cada script de construcción del proyecto haga referencia a sus dependencias externas (de terceros) desde un único directorio de "biblioteca" compartido local, con cada uno de esos binarios TOTALMENTE identificado por la versión:
%DirLibraryRoot%\ComponentA-1.2.3.4.dll
,%DirLibraryRoot%\ComponentB-5.6.7.8.dll
.Haga que cada script de construcción de proyecto publique la entrega principal en un único directorio de "salida" compartido local:
%DirOutputRoot%\ProjectA-9.10.11.12.dll
,%DirOutputRoot%\ProjectB-13.14.15.16.exe
.Haga que cada script de construcción de proyecto haga referencia a sus dependencias a través de rutas absolutas configurables y completamente versionadas (ver arriba) en los directorios "biblioteca" y "salida", Y EN NINGÚN OTRO LUGAR.
NUNCA permita 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" (ver arriba).
Haga que cada secuencia de comandos de compilación del proyecto haga referencia a sus herramientas de compilación necesarias mediante una ruta absoluta configurable y completamente versionada:
%DirToolRoot%\ToolA\1.2.3.4
,%DirToolRoot%\ToolB\5.6.7.8
.Hacer todos los proyectos del script de creación de contenido de código de referencia mediante una ruta absoluta relativa al directorio raíz del proyecto:
${project.base.dir}/src
,${project.base.dir}/tst
(sintaxis varía según la herramienta de construcción).SIEMPRE requiera un script de construcción del proyecto para hacer referencia a CADA archivo o directorio a través de una ruta absoluta y configurable (enraizada en un directorio especificado por una variable configurable):
${project.base.dir}/some/dirs
o${env.Variable}/other/dir
.NUNCA permita que un script de construcción de proyecto haga referencia a NADA con una ruta relativa como
.\some\dirs\here
o..\some\more\dirs
, SIEMPRE use rutas absolutas.NUNCA permita que un script de construcción de proyecto haga referencia a NADA utilizando una ruta absoluta que no tenga un directorio raíz configurable, como
C:\some\dirs\here
o\\server\share\more\stuff\there
.Para cada directorio raíz configurable al que hace referencia un script de construcción del proyecto, defina una variable de entorno que se utilizará para esas referencias.
Intente minimizar la cantidad de variables de entorno que debe crear para configurar cada máquina.
En cada máquina, cree un script de shell que defina las variables de entorno necesarias, que es específico para ESA máquina (y posiblemente específico para ese usuario, si es relevante).
NO coloque el script de shell de configuración específico de la máquina en el control de código fuente; en su lugar, para cada proyecto, envíe una copia del script en el directorio raíz del proyecto como plantilla.
REQUIERE que cada script de construcción del proyecto verifique cada una de sus variables de entorno y anule con un mensaje significativo si no están definidas.
REQUIERE que cada secuencia de comandos de compilación del proyecto verifique cada uno de los ejecutables de la herramienta de compilación dependiente, los archivos de la biblioteca externa y los archivos entregables del proyecto dependiente, y anule con un mensaje significativo si esos archivos no existen.
RESISTE la tentación de comprometer CUALQUIER archivo generado en el control de la fuente: sin entregables del proyecto, sin fuente generada, sin documentos generados, etc.
Si usa un IDE, genere todos los archivos de control del proyecto que pueda y no los confíe al control de código fuente (esto incluye los archivos de proyecto de Visual Studio).
Establezca un servidor con una copia oficial de todas las bibliotecas y herramientas externas, que se copiará / instalará en las estaciones de trabajo de los desarrolladores y en las máquinas de construcción. Realice una copia de seguridad junto con su repositorio de control de código fuente.
Establezca un servidor de integración continua (máquina de construcción) SIN herramientas de desarrollo en absoluto.
Considere una herramienta para administrar sus bibliotecas externas y entregables, como Ivy (utilizada con Ant).
NO uses Maven: inicialmente te hará feliz y eventualmente te hará llorar.
Tenga en cuenta que nada de esto es específico de Subversion, y la mayoría es genérico para proyectos dirigidos a cualquier sistema operativo, hardware, plataforma, lenguaje, etc. Usé un poco de sintaxis específica del sistema operativo y de la herramienta, pero solo como ilustración. -Confío en que lo traducirá a su sistema operativo o herramienta de elección.
Nota adicional sobre las soluciones de Visual Studio: ¡no las ponga en control de código fuente! Con este enfoque, no los necesita en absoluto o puede generarlos (al igual que los archivos de proyecto de Visual Studio). Sin embargo, creo que es mejor dejar los archivos de la solución a los desarrolladores individuales para que los creen / usen como mejor les parezca (pero no registrados en el control de código fuente). Yo guardo un
Rob.sln
archivo en mi estación de trabajo desde el que hago referencia a mis proyectos actuales. Dado que todos mis proyectos son independientes, puedo agregar / eliminar proyectos a voluntad (eso significa que no hay referencias de dependencia basadas en proyectos).No utilice externos de Subversion (o similares en otras herramientas), son un anti-patró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 ello. Cree un único script de shell que: tome parámetros del nombre del proyecto (como se enumeran en el repositorio) y el nombre de la etiqueta, cree un directorio temporal dentro de un directorio raíz configurable, verifique la fuente para el nombre del proyecto y el nombre de la etiqueta dados (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 debería incorporarse al control de código fuente como parte de su proyecto de "herramientas de construcción". Su servidor de integración continua puede utilizar este script como base para la creación de proyectos, o incluso puede proporcionarlo (pero es posible que desee el suyo propio).
@VonC: NO desea trabajar en todo momento con "ant.jar" en lugar de "ant-abcdjar" después de que se queme cuando se rompe el script de compilación porque, sin saberlo, lo ejecutó 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 ABCD) y su herramienta de compilación (Ant EFGH). 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 desde el principio.
fuente
Creo que Pragmatic Version Control usando Subversion tiene todo lo que necesita para organizar su repositorio.
fuente
Hemos configurado el nuestro para que coincida casi exactamente con lo que ha publicado. Usamos la forma general:
Aunque supongo que no es tan completo como su ejemplo, nos ha funcionado bien y nos permite mantener las cosas separadas. Me gusta la idea de que cada usuario también tenga una carpeta "Thrash"; actualmente, ese tipo de proyectos no terminan en el control de código fuente, y siempre sentí que deberían hacerlo.
fuente
¿Por qué tenerlo todo en un repositorio? ¿Por qué no tener un repositorio separado para cada proyecto (me refiero a "Solución")?
Bueno, al menos me he acostumbrado al enfoque de un proyecto por repositorio. Su estructura de repositorio me parece demasiado complicada.
¿Y cuántos proyectos planeas poner en este gran repositorio? 2? 3? 10? 100?
¿Y qué haces cuando cancelas el desarrollo de un proyecto? Simplemente elimínelo del árbol del repositorio para que sea difícil de encontrar en el futuro. ¿O dejarlo tirado para siempre? ¿O cuando quiere mover un proyecto a otro servidor por completo?
¿Y qué hay del lío de todos esos números de versión? Los números de versión de un proyecto son 2, 10, 11, mientras que el otro es 1, 3, 4, 5, 6, 7, 8, 9, 12 ...
Quizás soy tonto, pero me gusta un proyecto por repositorio.
fuente
Creo que la principal desventaja de la estructura propuesta es que los proyectos compartidos solo serán versionados con la primera solución a la que fueron agregados (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 reside en Solution1. Si necesita compilar desde esa rama en un momento posterior (versión QFE), utilizará la última versión de Project1 en lugar de la versión de Project1 en el momento de la rama.
Por esta razón, puede ser ventajoso colocar los proyectos compartidos en una o más soluciones compartidas (y por lo tanto, directorios de nivel superior en su estructura) y luego bifurcarlos con cada lanzamiento de cualquier solución.
fuente
Para agregar al problema de la ruta relativa:
No estoy seguro de que sea un problema:
simplemente revise Solution1 / trunk en el directorio llamado "Solution1", lo mismo para Solution2: el objetivo de los 'directorios' que realmente representan ramas es que no sean visibles una vez importados a un espacio de trabajo. Por lo tanto, las rutas relativas son posibles entre 'Solución1' (en realidad 'Solución1 / troncal') y 'Solución2' (Solución2 / troncal).
fuente
RE: la ruta relativa y el problema del archivo compartido -
Parece que esto es específico de svn, pero eso no es un problema. Otra persona ya mencionó repositorios separados y esa es probablemente la mejor solución que se me ocurre en el caso de que tenga diferentes proyectos que se refieran a otros proyectos arbitrarios. En el caso de que no tenga archivos compartidos, la solución OP (así como muchas otras) funcionará bien.
Todavía estamos trabajando en esto y tengo 3 esfuerzos diferentes (clientes diferentes) que tengo que resolver ahora mismo desde que asumí la configuración del control de versiones inexistente o deficiente.
fuente
Tengo un diseño similar, pero mi tronco, ramas, etiquetas en la parte superior. Entonces: / trunk / main, / trunk / utils, / branch / release /, etc.
Esto terminó siendo realmente ú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 los libros de texto.
fuente