Perdón por esta larga publicación, pero creo que vale la pena.
Acabo de comenzar con una pequeña tienda .NET que funciona de manera bastante diferente a otros lugares en los que he trabajado. A diferencia de cualquiera de mis posiciones anteriores, el software escrito aquí está dirigido a múltiples clientes y no todos los clientes obtienen la última versión del software al mismo tiempo. Como tal, no existe una "versión de producción actual". Cuando un cliente recibe una actualización, también obtiene todas las características agregadas al software desde su última actualización, que podría ser hace mucho tiempo. El software es altamente configurable y las funciones pueden activarse y desactivarse: las llamadas "funciones alternan". Los ciclos de lanzamiento son muy ajustados aquí, de hecho, no están programados: cuando se completa una característica, el software se implementa en el cliente correspondiente.
El equipo solo el año pasado se mudó de Visual Source Safe a Team Foundation Server. El problema es que todavía usan TFS como si fuera VSS y aplican bloqueos de Checkout en una sola rama de código. Cada vez que se coloca una corrección de errores en el campo (incluso para un solo cliente) simplemente construyen lo que está en TFS, prueban que el error se corrigió y se implementa en el cliente. (Yo mismo de un fondo de software de dispositivos médicos y farmacéuticos, ¡esto es increíble!). El resultado es que el código de desarrollo medio horneado se pone en producción sin siquiera ser probado. Los errores siempre se deslizan en las versiones de lanzamiento, pero a menudo un cliente que acaba de obtener una versión no verá estos errores si no usan la función en la que se encuentra el error. El director sabe que esto es un problema ya que la compañía está empezando a crecer. de repente con la llegada de algunos grandes clientes y otros más pequeños.
Me han pedido que analice las opciones de control de código fuente para eliminar la implementación de código defectuoso o inacabado, pero no sacrificar la naturaleza algo asíncrona de los lanzamientos de los equipos. He usado VSS, TFS, SVN y Bazaar en mi carrera, pero TFS es donde ha estado la mayor parte de mi experiencia.
Anteriormente, la mayoría de los equipos con los que he trabajado utilizan una solución de dos o tres ramas de Dev-Test-Prod, donde durante un mes los desarrolladores trabajan directamente en Dev y luego los cambios se fusionan con Test y luego con Prod, o se promocionan "cuando está hecho" en lugar de en Un ciclo fijo. Se utilizaron construcciones automatizadas, utilizando Cruise Control o Team Build. En mi trabajo anterior, Bazaar se usaba sentado en la parte superior de SVN: los desarrolladores trabajaban en sus propias ramas de características pequeñas y luego empujaban sus cambios a SVN (que estaba vinculado a TeamCity). Esto fue bueno porque fue fácil aislar los cambios y compartirlos con las ramas de otras personas.
Con ambos modelos había una rama central de desarrollo y producción (y a veces prueba) a través de la cual se introducía el código (y las etiquetas se usaban para marcar las compilaciones en la producción desde las que se realizaban las versiones ... y estas se convirtieron en ramas para corregir errores) a lanzamientos y fusionados de nuevo a dev). Sin embargo, esto realmente no se ajusta a la forma de trabajar aquí: no hay un orden para cuando se lanzarán varias funciones, se presionarán cuando estén completas.
Con este requisito, el enfoque de "integración continua", tal como lo veo, se rompe. Para sacar una nueva característica con una integración continua, debe empujarse a través de dev-test-prod y eso capturará cualquier trabajo inacabado en dev.
Estoy pensando que para superar esto deberíamos seguir un modelo ramificado con muchas características sin ramas de desarrollo de prueba, sino que la fuente debería existir como una serie de ramas de características que cuando se completa el trabajo de desarrollo se bloquean, prueban, arreglan y bloquean , probado y luego lanzado. Otras ramas de características pueden tomar los cambios de otras ramas cuando lo necesiten / quieran, por lo que eventualmente todos los cambios serán absorbidos por todos los demás. Esto encaja mucho en un modelo de bazar puro de lo que experimenté en mi último trabajo.
Por flexible que parezca, parece extraño no tener una troncal de desarrollo o una rama de producción en algún lugar, y me preocupa que las ramas no se vuelvan a integrar, o que se realicen pequeños cambios tardíos que nunca se transfieren a otras ramas y los desarrolladores se quejan de fusionar desastres ...
Qué piensa la gente sobre esto?
Una segunda pregunta final: estoy algo confundido acerca de la definición exacta del control de fuente distribuida: algunas personas parecen sugerir que se trata simplemente de no tener un repositorio central como TFS o SVN, algunos dicen que se trata de estar desconectado (SVN está 90% desconectado y TFS tiene un modo fuera de línea perfectamente funcional) y otros dicen que se trata de Ramificación de características y facilidad de fusión entre ramas sin relación padre-hijo (¡TFS también tiene fusión sin fundamento!). ¡Quizás esta sea una segunda pregunta!
Respuestas:
¿Qué define un DVCS?
La distribución en DVCS significa que cada clon de un repositorio tiene toda la información requerida para confirmar, actualizar, bifurcar, fusionar o buscar cualquier revisión en ese repositorio, sin tener que tocar un servidor . Lo único que puede hacer sin conexión
svn
es editar los archivos : necesita acceso al servidor para casi todos lossvn
comandos, incluido hacer algo tan simple como greppingsvn log
, por lo que en realidad está más cerca del 0% que del 90%.Cualquier repositorio central autorizado que pueda configurar en un flujo de trabajo DVCS es solo otro clon , y el único momento que necesita para interactuar con él es cuando retira las actualizaciones de otras personas o cuando empuja sus propios cambios para que otras personas puedan verlos. , prácticamente todo lo demás se puede hacer fuera de línea.
¿Qué modelo de ramificación es apropiado?
He estado en la situación en la que te encuentras ahora. Tales sistemas pueden ser un verdadero dolor, pero hay que entender las razones pragmáticas en que se convirtieron así y darse cuenta de que no están más allá de la redención . Se han desarrollado muchas herramientas que pueden ayudar a gestionar este tipo de complejidad .
Antes que nada, hagas lo que hagas, no muestres a las personas el exitoso modelo de ramificación git , solo los confundirá y los apagará. En cambio, desarrolle su propio modelo que refleje su flujo de trabajo existente , pero resuelva los problemas con su flujo de trabajo existente .
Algunos recursos que es posible que desee considerar incluyen cosas como submódulos git que permitirán que diferentes versiones de clientes especifiquen diferentes combinaciones de configuración de cliente, módulos de aplicación y bibliotecas. Otra opción sería el uso de un sistema de administración de parches para aplicar colas de parches específicas del cliente / producto.
Ambas opciones proporcionarán mucha más flexibilidad, transparencia y seguridad que su flujo de trabajo actual, y podrían ser más fáciles de usar que una estrategia de sucursal aún más compleja. Ciertamente desearía tener acceso a estas herramientas cuando estaba en su situación.
Para obtener más información sobre estas opciones, consulte mis respuestas a Estrategia para usar el control de versiones en un sistema modular , ¿Cómo usar el repositorio de Subversion dentro del repositorio de Git? y control de Fuente / Versión para la aplicación utilizada por múltiples compañías .
En última instancia, esto es realmente algo que tendrá que desarrollar con el resto del equipo. Si tiene la visión de proponer algo que funcione mejor que lo que ya tiene, y pueda obtener la aceptación de sus colegas desarrolladores, entonces será mucho más fácil.
Lo más importante es mostrar a tus colegas cómo lo que propones les facilitará la vida . Una vez que están convencidos, tiene muchas más posibilidades de lograr que la administración deseche su inversión en TFS y comience a usar un modelo más apropiado para sus métodos de trabajo.
fuente
En primer lugar, DVCS es una pista falsa para los problemas que tiene: la herramienta de control de versiones en uso no es la raíz de los problemas que deben resolverse. Puede ser que haya aspectos de las soluciones de DVCS que son "mejores" que TFS, pero no es lo que debe corregirse en este momento.
Ha identificado que necesita una estructura de ramificación viable que se adapte a su organización; creo que encontrará que todavía tiene un enlace troncal, cuando se completa una característica, se fusiona nuevamente en el enlace troncal y se cierra. También hay algunas buenas ideas sobre cómo implementar dependencias comunes.
También necesita que funcione la integración continua (no hay razón para no tener una compilación automatizada para todas y cada una de las ramas activas para darle la confianza de que puede construir esa rama y que pasa las pruebas pertinentes). Me incomoda que un commit (o al menos un "push") no desencadene una construcción para mí.
Y debe comenzar con las pruebas automatizadas en todos los niveles, pero especialmente las pruebas unitarias y las pruebas de integración para comenzar a reducir las posibilidades de que nuevos errores escapen a la naturaleza. Esto último es enorme y es algo con lo que todavía estoy luchando, pero está claro que una vez que sepas que puedes construir cosas, todo esto tendrá el mayor valor.
Debe combinar esto con asegurarse de que sus paquetes de implementación provengan de su servidor de compilación y que la implementación esté lo más automatizada posible (debe poder pasar del artefacto del servidor de compilación al código de implementación en vivo con un esfuerzo mínimo y un estrés mínimo).
Hmm, supuse que hay una buena configuración de seguimiento de problemas bien ordenada ... tú también la necesitas y para estar seguro de que se está utilizando correctamente. Idealmente, desea que sus aplicaciones en vivo realicen errores en este sistema (o para la clasificación) automáticamente.
Por último, no intente resolver todos sus problemas a la vez: la construcción y la prueba me parecen ser los lugares en los que debe centrarse primero.
fuente
La segunda pregunta es más fácil y más corta, así que intentaré comenzar desde allí.
DVCS es un sistema en el que no hay una fuente de código "autorizada" (excepto "por acuerdo", cuando se usa) y el intercambio de datos P2P es posible sin niveles adicionales (definición personal, no canónica)
Sobre el tema la primera pregunta
Me temo que la empresa debe reconstruir el flujo de trabajo y repensar el estilo para obtener "un código predecible y administrado de alguna manera". No puedo decir acerca de TFS (excepto la opinión personal y el sentimiento, que es un sistema débil en la combinación de control de versión / sin base es malo /), pero para cualquier VCS en su situación ("Producto" es un conjunto de "Módulos" independientes, cada "Cliente" obtiene diferentes "Productos": ¿es correcta esta suposición?) Prefiero dividir el desarrollo de módulos en ramas separadas, tener el Producto como "Supermódulo" (¿también rama?), allí cada módulo está vinculado a una revisión específica del módulo. branch, module-development utiliza el paradigma branch-per-task (y module-branch consta solo de conjuntos de fusión).
De esta manera, siempre puede saber qué "Colección" (es decir, un conjunto de módulos y sus revisiones correspondientes) forma cada "Producto", tiene la posibilidad de hacer CI (para ramas de tareas terminadas y fusionadas ), Pruebas unitarias y Compilaciones
fuente
Pregunta principal del anuncio: creo que de lo que está hablando es exactamente de qué se trata el modelo de ramificación exitoso de git (y el flujo de git de la herramienta auxiliar para apoyarlo). Tenga una rama maestra, que siempre esté en estado desplegable y haga todo el trabajo en las ramas de características.
También puede usar el proceso utilizado por git, que se deriva del mismo principio básico. En el desarrollo de git-core, todo el trabajo ocurre en ramas de características. Las ramas de características se envían al integrador, que ejecuta un script para fusionarlas todas para crear una rama llamada
pu
(actualizaciones propuestas). Varias personas toman esta rama y trabajan con ella para probarla.En lugar de integrador, puede hacer que el servidor de integración continua haga esta fusión al comienzo de una compilación. De esa manera, cuando alguien del equipo empuje los cambios al repositorio central como una rama de características (probablemente usando alguna convención de nomenclatura para indicar qué ramas deben seleccionarse).
En git, la rama de características de la que procede
next
,master
omaint
dependiendo de la versión a la que se dirige (maint es para corregir la versión actual, master para la versión actual en preparación y la siguiente para la siguiente), pero no tendrá tantas.Mientras las características están en
pu
("cocinando" en la terminología del mantenedor de git), se rebobinan y lapu
rama se descarta y se crea de nuevo cada vez, lo que hace que sea más fácil de revisar, pero no es adecuado para basar otro trabajo. Cuando la rama de características se fusiona en una de las líneas principales, se cierra para rebobinar y se realizan correcciones adicionales como nuevas confirmaciones.Yo personalmente recomendaría lo
git
mejor. Al principio es un poco más difícil de aprender, porque crece más orgánicamente, pero al final parece más flexible. Pero cualquiera de los tres sistemas distribuidos, git, mercurial y bazar le servirá bien (y a menudo puede incluso mezclarlos, por ejemplo, mercurial puede tirar y empujar hacia / desde el repositorio de git y creo que también puede bazar).Segunda pregunta del anuncio: me enseñaron que "distribuido", en general, significa que puedes mover objetos y mantener su identidad. Que es exactamente lo que hace el control de versión distribuido: clonas el repositorio y contiene las mismas confirmaciones y permite hacer las mismas cosas con ellos. La facilidad de ramificación y la operación desconectada son las principales características a nivel de usuario que se derivan del principio de mover confirmaciones y el diseño gráfico dirigido que lo permite.
fuente
Desafortunadamente, no hay una solución conocida para los errores en el código :)
Entonces, solo busca evitar que los registros inacabados se vean atrapados en la versión principal, y la única respuesta a eso es la fusión de trabajo de sucursal para cada desarrollador. Lo hice en una empresa anterior que usaba Clearcase, funcionó bastante bien (a pesar de que teníamos que tener una docena de administradores de clearcase).
Ahora, supongo también que realiza la corrección de errores en la versión del producto que cada cliente tiene actualmente ... por lo que tiene un problema de fusión al traer correcciones de errores desde la versión A hasta la versión Z. No hay una manera fácil de lidiar con esto, pero tendrá que tener una rama para cada versión enviada. La mejor manera de lidiar con esto es mantener las ramas de características solo en la última versión, y hacer que los clientes actualicen para obtener las nuevas características, al mismo tiempo, realizar la corrección de errores directamente en la rama de lanzamiento y fusionarlas hacia arriba con todas las otras ramas de lanzamiento cuando se complete
No es muy agradable, pero puede funcionar notablemente bien. Mantiene el código organizado y bien separado. También es fácil de entender para los otros desarrolladores: pequeñas correcciones de errores directamente en "el código", cualquier cosa más que un par de líneas se realiza en una rama dedicada donde pueden tardar todo el tiempo que deseen completarlo. (¡¡tendrás que resolver los problemas de fusión y asegurarles que está bien si 2 desarrolladores trabajan en 2 funciones al mismo tiempo !!)
Después de un tiempo, también puede introducir ramas de características en las ramas de lanzamiento, donde los errores se corrigen y luego se combinan, pero en mi humilde opinión, esto suele ser más esfuerzo de lo necesario. Sin embargo, si necesita agregar funciones a versiones anteriores, deberá seguir este enfoque: bifurcarse de una rama de versión, luego fusionar el código nuevamente en esa versión y combinar el cambio hacia arriba a las versiones posteriores también. Eso hará que su equipo de prueba esté muy descontento, ya que las versiones se retrasarán mucho debido a la necesidad de probar varias versiones repetidamente, y el equipo de desarrollo estará descontento ya que tendrán que fusionarse mucho antes de que puedan comenzar con el nuevo código (en mi empresa actual esto sucede, principalmente debido a la cantidad de trabajo que tenemos que siempre debe completarse lo antes posible).
DVCS:
Básicamente, un DVCS es donde todos tienen su propia copia del repositorio del servidor. Tiene algunas ventajas (especialmente en equipos distribuidos con comunicación limitada), pero también tiene algunas desventajas, así que compruébelo antes de cambiar a un DVCS. Si eres una tienda de Windows, entonces probablemente encontrarás que Mercurial es el mejor DVCS para ti.
fuente