svn - trabajar - Estructura de Proyectos en Control de Versión
svn tutorial español (9)
Sé que hay al menos 10 formas diferentes de estructurar proyectos en el control de versiones. Tengo curiosidad por saber qué métodos se usan y cuáles funcionan para ti. He trabajado con SVN, TFS y actualmente / desafortunadamente VSS. He visto el control de versiones implementado muy mal y simplemente está bien, pero nunca genial.
Para que todo salga a la luz, aquí hay una reseña de las cosas que he visto.
Este ejemplo está basado en SVN, pero se aplica a la mayoría de los VCS (no tanto al control de versión distribuida).
ramificar los proyectos individuales que forman parte de site / division / web / projectName / vb / src / [trunk | branches | tags]
ramificar todo el sitio, en el caso que he visto, se ramificó todo el sitio, excepto los componentes principales. / division / [trunk | branches | tags] / web / projectName / vb / src /
Use main-line como una rama predeterminada, solo cuando sea necesario para grandes cambios.
¿Qué ocurre con las dependencias externas como AJAXTookit o alguna otra extensión de terceros que se utiliza en varios proyectos?
El control de origen es para código fuente, no binarios. Mantenga las asambleas / jarrones de terceros en un repositorio separado. Si trabajas en el mundo Java prueba algo como Maven o Ivy. Para proyectos .Net una unidad compartida simple puede funcionar bien siempre y cuando tenga políticas decentes sobre cómo se estructura y se actualiza.
Como tenemos todos los artefactos y la construcción en el mismo árbol tenemos algo así como:
El maletero
- Planificación y seguimiento
- Req
- Diseño
- Construcción
- Compartimiento
- Base de datos
- Lib
- Fuente
Desplegar
- Control de calidad
- MAMÁ
Creo que las políticas y los procedimientos de SCM que adopte un equipo dependerán en gran medida del proceso de desarrollo que estén utilizando. Si tiene un equipo de 50 personas con varias personas trabajando en cambios importantes simultáneamente y lanzamientos que solo ocurren cada 6 meses, tiene mucho sentido que cada uno tenga su propia sucursal donde puede trabajar en forma aislada y solo fusionarse en cambios de otras personas cuando él los quiere. Por otro lado, si usted es un equipo de 5 personas sentadas en la misma habitación, tiene sentido ramificarse con mucha menos frecuencia.
Asumiendo que está trabajando en un equipo pequeño donde la comunicación y la colaboración son buenas y las entregas son frecuentes, tiene muy poco sentido siempre ramificar a la OMI. En un proyecto, simplemente lanzamos el número de revisión de SVN en el número de versión del producto para todas nuestras versiones y ni siquiera lo etiquetamos. En el raro caso de que hubiera una falla crítica encontrada en prod, simplemente ramificaríamos directamente desde la revisión que fue lanzada. Pero la mayoría de las veces simplemente arreglamos el error en la rama y lo liberamos de la cajuela al final de la semana según lo programado. Si sus lanzamientos son lo suficientemente frecuentes, casi nunca se encontrará con un error que no puede esperar hasta el próximo lanzamiento oficial.
Trabajé en otros proyectos en los que nunca hubiéramos salido con la tuya, pero debido al proceso de desarrollo liviano y la poca ceremonia, pudimos utilizar una política de control de versiones livianas de manera muy efectiva.
También mencionaré que todo lo que he escrito proviene de un contexto de TI empresarial donde solo hay una instancia de producción de una base de código determinada. Si estuviera trabajando en un producto que se implementó en 100 sitios diferentes de clientes, las prácticas de bifurcación y etiquetado tendrían que ser un poco más intensas para administrar todos los ciclos de actualización independientes en todas las instancias.
Ejemplo para SVN:
el maletero/
rama/
etiquetas /
El tronco debe mantenerse en un punto donde siempre puedas empujar una liberación desde él. No debe haber grandes errores que conozca (por supuesto que habrá eventualmente, pero eso es lo que debería esforzarse).
Cada vez que necesite crear una nueva característica, realice un cambio de diseño, sea lo que sea, bifurque. Marque esa rama al comienzo. Luego, cuando haya terminado con la rama, etiquetela al final. Esto ayuda con la fusión de nuevo en el tronco.
Cada vez que necesites presionar un lanzamiento, etiqueta. De esta forma, si algo sale mal, puede retroceder a la versión anterior.
Esta configuración mantiene el tronco lo más limpio posible y le permite corregir rápidamente los errores y expulsarlos mientras mantiene la mayoría de su desarrollo en las ramas.
Editar: para cosas de terceros, depende. Si puedo evitarlo, no lo tengo bajo control de fuente. Lo guardo en un directorio fuera del control de código fuente y lo incluyo desde allí. Para cosas como jquery, lo dejo bajo control de fuente. La razón es que simplifica mi script para empujar. Simplemente puedo hacer que haga una exportación svn y rsync.
Migramos del mal mundo de VSS con un repositorio gigante (más de 4G) antes de cambiar a SVN. Realmente tuve problemas con la configuración del nuevo repositorio para nuestra empresa. Nuestra compañía es una escuela muy "vieja". Es difícil conseguir el cambio. Soy uno de los desarrolladores más jóvenes y ¡tengo 45 años! Soy parte de un equipo de desarrollo corporativo que trabaja en programas para varios departamentos de nuestra compañía. De todos modos, configuré nuestros directorios como este
+ devroot
+--Dept1
+--Dept1Proj1
+--Dept2Proj2
+--Dept2
+--Dept2Proj1
+--Tools
+--Purchase3rdPartyTools
+--NLog
+--CustomBuiltLibrary
Quería incluir la posibilidad de rama, pero sinceramente eso es demasiado en este punto. Junte cosas con las que todavía tenemos problemas usando este esquema.
- Es difícil solucionar los problemas de producción si está trabajando en una actualización importante del producto (es decir, porque no hacemos ramificaciones)
- Es difícil gestionar el concepto de promoción de "Dev" a "Prod". (Ni siquiera preguntes sobre promocionar a QA)
Para mis proyectos, siempre uso esta estructura.
- el maletero
- config
- documentos
- sql
- inicial
- actualizaciones
- src
- aplicación
- prueba
- tercero
- lib
- herramientas
- etiquetas
- ramas
- config: se usa para almacenar las plantillas de configuración de mi aplicación. Durante el proceso de compilación, tomo estas plantillas y reemplazo los marcadores de posición de los tokens con los valores reales, según la configuración que estoy haciendo.
- documentos: toda la documentación de la aplicación se coloca aquí.
- sql - Rompo mis scripts sql en dos directorios. Uno para la configuración inicial de la base de datos para cuando comienzas de nuevo y otro lugar para mis scripts de actualización que se ejecutan basados en el número de versión de la base de datos.
- src - Los archivos fuente de la aplicación. Aquí rompo los archivos fuente basados en la aplicación y las pruebas.
- tercero: aquí es donde coloco las bibliotecas de terceros a las que hago referencia dentro de mi aplicación y que no están disponibles en el GAC. Lo dividí en base a lib y herramientas. El directorio lib contiene las bibliotecas que deben incluirse con la aplicación real. El directorio de herramientas contiene las bibliotecas a las que hace referencia mi aplicación, pero solo se usan para ejecutar pruebas unitarias y compilar la aplicación.
Mi archivo de solución se coloca justo debajo del directorio troncal junto con mis archivos de compilación.
Practicamos el desarrollo altamente componente utilizando Java, tenemos alrededor de 250 módulos en el tronco que tienen ciclos de vida independientes. Las dependencias se gestionan a través de Maven (es una buena práctica allí), cada iteración (dos veces por semana) los módulos desarrollados activamente se etiquetan con una nueva versión. Números de versión de 3 dígitos con semántica estricta (major.minor.build - cambios importantes significan incompatibilidad hacia atrás, cambios menores significan compatibilidad hacia atrás y cambios en el número de compilación significan compatibilidad con versiones anteriores y posteriores). Nuestro último producto de software es un ensamble que atrae docenas de módulos individuales, nuevamente como dependencias de Maven.
Ramificamos módulos / ensamblajes cuando necesitamos corregir errores o mejorar una versión lanzada y no podemos entregar la versión HEAD. Después de haber etiquetado todas las versiones hace que esto sea fácil pero las sucursales aún incurren en una sobrecarga administrativa significativa (específicamente manteniendo las sucursales sincronizadas con ciertos conjuntos de cambios HEAD) que en parte son causadas por nuestras herramientas, Subversion no es óptima para administrar sucursales.
Encontramos que una estructura de árbol bastante plana y sobre todo predecible en el repositorio es crucial. Nos ha permitido crear herramientas de lanzamiento que eliminan el dolor y el peligro de un proceso de lanzamiento manual (notas de la versión actualizadas, compilaciones de proyectos, pruebas de unidades ejecutadas, etiquetas creadas, no hay dependencias SNAPSHOT, etc.). Evite poner demasiada categorización u otra lógica en la estructura de su árbol.
Más o menos hacemos algo como lo siguiente:
svnrepo/
trunk/
modules/
m1/ --> will result in jar file
m2/
...
assemblies/
a1/
...
tags/
modules/
m1/
1.0.0/
1.0.1/
1.1.0/
m2/
...
assemblies/
a1/
iteration-55/
...
branches/
m1/
1.0/
...
Para las dependencias externas, no puedo exagerar el énfasis en algo como Maven: administre sus dependencias como referencias a artefactos binarios versionados, identificados de manera única en un repositorio.
Para la estructura del módulo / proyecto intenal: apegarse a un estándar. La uniformidad es la clave. Nuevamente, Maven puede ayudar aquí ya que dicta una estructura. Muchas estructuras están bien, siempre y cuando te apegues a ellas.
Prefiero repositorios estructurados, muy organizados, independientes y detallados. Hay un diagram ilustra el enfoque general (ideal) del proceso de mantenimiento del repositorio. Por ejemplo, mi estructura inicial de repositorio (cada repositorio de proyecto debería tener) es:
/project
/trunk
/tags
/builds
/PA
/A
/B
/releases
/AR
/BR
/RC
/ST
/branches
/experimental
/maintenance
/versions
/platforms
/releases
PA
significa pre-alfa A
significa alfa B
significa beta AR
significa alfa-release BR
significa beta-release RC
significa liberación del candidato ST
significa estable
Hay diferencias entre compilaciones y lanzamientos .
- Las etiquetas en la carpeta de compilaciones tienen un número de versión correspondiente a un patrón
NxK
, dondeN
yK
son enteros. Ejemplos:1.x.0
,5.x.1
,10.x.33
- Las etiquetas en la carpeta de lanzamientos tienen un número de versión correspondiente a un patrón
NMK
, dondeN
,M
yK
son enteros. Ejemplos:1.0.0
,5.3.1
,10.22.33
.
Recientemente, he desarrollado una capacitación dedicada a Software Configuration Management donde describo el enfoque de numeración de versiones y por qué exactamente esta estructura de repositorio es la mejor. Aquí hay diapositivas de presentación .
También está mi answer sobre la question sobre "Repositorios SVN múltiples frente a repositorio de una sola compañía". Puede ser útil siempre que aborde este aspecto de la estructuración del repositorio en su pregunta.
Puedo apreciar la lógica de no poner binarios en el repositorio, pero creo que también hay una gran ventaja. Si desea poder sacar una revisión específica del pasado (generalmente una etiqueta más antigua) me gusta poder tener todo lo que necesito provenga de la verificación de svn. Por supuesto, esto no incluye Visual Studio o .NET Framework, pero tener la versión correcta de nant, nunit, log4net, etc. hace que sea muy fácil pasar de la compra a la compilación. De esta manera, comenzar es tan fácil como "svn co project" seguido de "nant build".
Una cosa que hacemos es poner los binarios de ThirdParty en un árbol separado y usar svn: external para traer la versión que necesitamos. Para facilitar la vida, tendremos una carpeta para cada versión que se haya utilizado. Por ejemplo, podríamos traer la carpeta ThirdParty / Castle / v1.0.3 al proyecto actual. De esta forma, todo lo que necesita para construir / probar el producto está dentro o debajo de la raíz del proyecto. La compensación en el espacio del disco bien vale la pena en nuestra experiencia.