Nov 29

git flow

git-flow

( Imagen de Our Workflow: git-flow

Hace poco, viendo un vídeo, descubrí git-flow.

Siempre había oído, tanto en git como en subversion, que hay que tener una rama de desarrollo, una rama para versiones estables, hacer ramas para cada nueva funcionalidad que se va a implementar, etc, etc. Pero siempre me ha parecido muy lioso. Los comandos de crear ramas y juntarlas tanto en subversion como en git, si bien no son especialmente complicados, si son varios comandos a ejecutar para cada una de esas tareas a hacer y requieren que todos los del equipo seamos muy rigurosos para hacerlo bien.

Pues bien, hay una herramienta para git, llamada git-flow, que justamente nos facilita la ejecución de esos comandos, haciendo que el proceso de crear las ramas para cada nueva funcionalidad, para cada nueva release, para corregir bugs, sea bastante más sencilla.

Con git-flow hay dos ramas principalmente. La rama master, en la que están las versiones estables de nuestro software, convenientemente etiquetadas, y la rama development, en la que se hace el desarrollo. La creación de estas ramas es muy sencilla una vez instalado git-flow, basta ejecutar

$ git flow init

Si queremos empezar a trabajar en una nueva funcionalidad, debemos crear una rama para ella que parte de la rama development. Nuevamente, con git-flow es inmediato

$ git flow feature start NOMBRE

donde NOMBRE es el nombre que queramos para la rama. Yo suelo poner el número de tarea de jira. El comando de git-flow crea la rama feature/NOMBRE y nos hace el checkout de ella para que podamos empezar a trabajar. Podemos subirla al servidor si queremos que más desarrolladores trabajen en ella, o dejarla en nuestro git local si sólo vamos a trabajar nosotros. Una vez terminada y probada la funcionalidad, hay que llevarla a la rama development, que se hace con el siguiente comando

$ git flow feature finish NOMBRE

Esto hace el merge de nuestra funcionalidad sobre la rama de desarrollo … y borra la rama de la funcionalidad, es decir, se borra la rama feature/NOMBRE, aunque los commit que hicimos en ella se han pasado a la rama de desarrollo.

Si quisieramos hacer una nueva entrega de nuestro software, es decir, pasar una nueva versión de la rama de desarrollo a la rama estable master, el comando de git-flow es

$ git flow release start VERSION

Esto crea una nueva rama release/VERSION donde podemos tener congelada este nuevo candidato a versión, hacer los cambios que consideremos necesarios para pasar a nueva versión (por ejemplo, cambiar en número de versión en los ficheros pom.xml o build.gradle, cambiar niveles de log, ficheros de configuración o lo que sea). Una vez que nuestra nueva versión está "fetén", para llevarla a la rama master el comando es

$ git flow release finish VERSION

Esto lleva los cambios de release/VERSION tanto a la rama master como a la rama de desarrollo. Etiqueta la rama master con una etiqueta que nos pide y que puede ser en número de versión o lo que queramos. Y finalmente, borra la rama release/VERSION.

Finalmente, si en la rama estable master encontráramos un bug que hubiera que corregir, git flow permite crear una rama directamente sobre la master para corregir el bug. El comando sería

$ git flow hotfix start BUG

Esto crea una rama hotfix/BUG para que corrijamos el bug. Una vez corregido, hay que llevar los cambios a master y suele ser buena idea llevarlos también a la rama de desarrollo, para que el bug quede corregido definitivamente. El comando es

$ git flow hotfix finish BUG

Esto lleva los cambios del bug tanto a master como a development, y borra la rama del bug.

Y esto es lo básico, bastante sencillo. Hay más comandos de git flow, y con opciones, pero con lo comentado aquí, así de sencillo, se tiene ya un flujo de trabajo sobre git bastante completito.

 

Aug 09

Se me han pasado las ganas de jugar con Git submodules

Sigo jugando con Git y lo siguiente que me apetecía probar era el tema de git submodule. Con ellos puedes construir un proyecto/repositorio de Git en el que algunos de los directorios son otros proyectos/repositorios de git. De esta forma tienes un "super repositorio" compuesto de varios pequeños repositorios (aparte de tener su propio código).

Me pongo a ello, a mirar en google cómo se hace y veo que es un poco liado. Finalmente este tutorial me quita las ganas de probarlo. Git tiene unas pequeñas restricciones que hace que la creación de módulos sea un poco laboriosa y "pesadita"

  • En un repositorio bare no se pueden hacer commits.
  • No se puede clonar como submodulo un repositorio vacío.
  • No se puede añadir un submodulo en un repositorio bare.
  • No se puede hacer push si el origin es un repositorio no bare

Con todo esto el proceso de creación es tan complicado como lo siguiente (puedo estar equivocado en algún detalle, sólo lo he leído, intentado probarlo rápidamente y desistido por ser algo pesado)

  • Creas los repositorios que harán de submodulos como repositorios normales (no bare) y haces algún commit en ellos (si es bare no puedes  hacer el commit)
  • Los clonas para convertirlos en bares, pero con git config tienes que tocar manualmente las referencias en la copia, para que el bare no tenga como origen el repositorio normal.
  • Creas el super repositorio como repositorio normal y haces algún commit en él.
  • Convertimos el super repositorio en bare haciendo otro clone y tocando nuevamente las referencias a mano con git config.
  • Hacemos otro clone más del super repositorio bare y entonces añadimos los submodulos en la copia. Hacemos commit y push al repositorio central.

y tras este "simple" proceso está más o menos listo, salvo el detalle de que si un segundo desarrollador clona el super repositorio, tiene que acordarse de ejecutar git submodule init y git submodule update para que los submodulos realmente se clonen … ¿cómo hacemos estos comandos en un hudson por ejemplo? ¿O hudson lo tiene controlado?

Y bueno, si sólo fuera el proceso de crearlos, aun se podía plantear hacerlo (eso se hace sólo una vez en la vida de cada proyecto y lo hace el que crea el repositorio, supuestamente una persona avezada en git). El problema son los "gotchas" que vienen en el tutorial anterior. Indica que siempre hay que acordarse de publicar los cambios en los submodulos ANTES que los cambios en el superproyecto. Me hace a mí que en un grupo relativamente grande de desarrolladores, alguno se va a equivocar con bastante frecuencia. Aunque todo es cuestión de aprender el truco y convertirlo en hábito : "siempre commit y push de los submódulos primero".

Está bien saber que existen los submodulos de git por si algún día hacen falta. De hecho, trabajando en java es algo que echo de menos cuando tenemos muchos proyectos independientes pero que comparten juegos de ficheros no java comunes. Por ejemplo, juegos de iconos, dlls de windows, ficheros de script o ficheros de configuración (xml, properties, etc). La solución de "copiar" todo ese juego de ficheros en cada proyecto es un poco pesada, pero si no se copia es dificil hacer automáticamente un zip de instalación que tenga todos esos ficheros. La solución que se me ocurre es hacer un repositorio git con todo ese juego de ficheros y añadirlo como submodulo en los proyectos que lo necesiten.

En cualquier caso, queda pendiente para más adelante. Ahora me he puesto a jugar con Spring Framework WEB/MVC 😉

Aug 02

Instalando el servidor de Git en Windows

Jugando toda esta semana, al final he conseguido instalar un servidor de Git en Windows.

La instalación de Git es ahora fácil al haber un instalador de Windows. Eso sí, para ser usado a través de bash para Git o de Cygwin, puesto que la opción de meterlo en el PATH de Windows no está aconsejada.

El git daemon quedó totalmente descartado al no tener autentificación de usuarios y quedarse colgado en Windows cuando se intenta un pull.

Así que me puse a intentar la siguiente opción de servidor, el ssh. Windows no lleva servidor de ssh, así que hay que buscarse uno. Primero probé con servidores específicos de Windows, gratuitos, en concreto FreeSSHd, La instalación muy sencilla y además coge los usuarios de Windows, por lo que lo tengo funcionando rápidamente. Un cliente ssh puede conectarse y obtiene un cmd de Windows remoto. El problema viene al intentar integrarlo con Git. Al ser un cmd de Windows, no tiene en el PATH los comandos de Git, Es más, no necesita los comandos de git que vienen en el directorio bin, sino algunos de los que vienen en el directorio libexec/git-core y alguna dll de bin. Tras copiar los ejecutables concretos y dlls concretas que hacen falta en C:\Windows, ya intenta funcionar el git clone ssh://… … pero sólo lo intenta, da error. Buscando en google, me encuentro con que mucha gente tiene el mismo problema, que nadie da solución y que aparentemente FreeSSHd devuelve algún caracter que no le gusta al protocolo de git y va mal, posiblemente los famosos retornos de carro /r/n o sólo /n, por lo que descarto el servidor FreeSSHd para usar con Git. Busqué otros servidores SSH de Windows, pero no encontré ninguno gratuito o que me convenciera.

Así que intenté OpenSSH para Windows, una instalación mínima de cygwin con OpenSSH para Windows. No conseguí hacerlo funcionar rápidamente, posiblemente debido a algún problema en el PC donde hice las pruebas, así que pasé a la siguiente opción, instalar cygwin con git y openssh. La guía del enlace anterior es una maravilla, exactamente lo que necesitaba y funcionó a la primera, incluso instalando OpenSSH como servicio de Windows e importando los usuarios propios de Windows. Un git clone ssh://  también funcionó bien sin problemas …. pero ya sabemos que esto de la programación no es tan maravilloso como parece y siempre hay algún "pero". El único problema, que mucha gente tiene en google y que nadie parece haber resuelto, es que no se pueden clonar repositorios de otros discos que no sean el C:\. Cosas como ssh://host/D:/repo, ssh://host/d/repo o ssh://host/cygdrive/d/repo no funcionan. Como todos sabemos, es buena costumbre en Windows dejar C:\ para el sistema operativo y meter nuestros datos en otro disco (D:\ por ejemplo), así que esta opción, aunque va con repositorios en C:\, no me convence.

ACTUALIZACIÓN: Lo de usar distinto drive está funcionando. Desinstalé el git de windows e instalé el de cygwin a través del setup.exe de cygwin. Ya lo había hecho al instalar el OpenSSH. Ahora git clone ssh://localhost/cygdrive/e/repo funciona correctamente. Quizás el fallo se debiera a lguna incompatibilidad entre los paths del git de Windows que te bajas de http://git-scm.com/ y el de cygwin. 

Así que me cogí los servidores de Git de este comentario y me puse a ello. Una rápida búsqueda en Google para comparar y ver cómo se instalan en Windows me decidió rápidamente a probar gitblit. Entre esta guía de instalación de gitosis en windows y esta otra de gitblit (apartado GO: Single stack solution, con todas las dependencias integradas y 5 minutos para tenerlo funcionando), está claro. Viendo rápidamente el fichero de configuración de gitblit, veo que soporta LDAP, por lo que puedo intentar ponerlo en el Active Directory de Windows. Dicho y hecho, lo prometido por gitblit es cierto, en cinco minutos está funcionando bien y sin problemas. Sólo desempaquetar el zip, indicarle en el fichero de configuración el path donde están tus repositorios y arrancarlo con doble click. La integración con Active Directory me costó un poco más, pero más por culpa de Microsoft que de gitblit, Active Directory no es exactamente igual que LDAP y me dio algún problema hasta encontrar la solución. (principalmente, si necesitas un usuario para consultar LDAP, el nombre de usuario es estilo "cn=jsmith,ou=usuarios,dc=compania,dc=com", mientras que en Active Directory el usuario es "John Smith", es decir, el nombre "expandido" y sin cn=, ou= ni dc=. El segundo problema el campo email. gitblit espera un campo email y Active Directory (al menos el nuestro) tiene uno mail (sin la e delante). Aguí gitblit lanza una excepción y no va. Afortunadamente, el fichero de propiedades de gitblit permite indicar cómo se llama este campo.

Me he quedado con ganas de hacer alguna prueba más con lo del disco no C:\ de OpenSSH y de probar el servidor scm-manager, pero creo que he jugado bastante, tengo servidor git "oficial" con gitblit funcionando y todavía me queda actualizar Hudson o instalarle el plugin correspondiente para que entienda de git.

Resumiendo, si tienes un servidor en Windows, quieres un servidor Git con los usuarios de Active Directory y no quieres "jugar" mucho tiempo, gitblit es una buena opción.

Jul 27

Jugando con GIT

Tras el post anterior, me quedé con las ganas de ponerme a jugar con Git un poco más en serio, y eso he estado haciendo, a ratos, a lo largo de esta semana.

La primera sorpresa agradable es que ahora, desde la página oficial, existe descarga para windows, con un instalador fácil estilo windows. Me lo descargo e instalo. El instalador te da tres opciones, instalar un bash específico para Git, hacer una instalación paa cygwin o bien, con serias advertencias por parte del instalador, poner los comandos de git accesibles desde una ventana de comandos de ms-dos. Esto último requiere que ciertos comandos de windows, como find.exe, se cambien por otros al estilo unix. Vemos que windows, aunque ya hay instalador fácil oficial, sigue sin estar totalmente soportado, haciéndose necesario el uso de una shelll de unix. Supongo que esto no tiene especial importancia si estás acostumbrado a unix (como es mi caso), vas a usar un TortoiseGIT o directamente el IDE que sea.

Siguiente parte a probar, el servidor. Según la documentación hay tres opciones:

  • git daemon. Es lo más simple, se arranca con un comando y ya está compartido cualquier repositorio git en el servidor. El acceso es de solo lectura, haca falta configurar el arranque si queremos también acceso de escritura. La pega es que tiene ningún tipo de autentificación de usuario, así que cualquier anónimo sería capaz de escribir y borrar en nuestro repositorio sin ninguna restricción. Es ese el motivo por el que no se aconseja esta opción en redes que no sean de confianza. Este servidor se aconseja sólo en modo lectura, puesto que es el más rápido a la hora de hacer descargas (git clone).
  • ssh. Acceso a través de ssh, con una configuración de ssh más o menos estándar. No la he probado y es la opción aconsejada, con la pega de que todos los usuarios deben tener usuario en el servidor.
  • http. Publicar un repositorio en modo lectura desde un servidor http es casi inmediato. La parte de escritura requiere habilitar WebDAV en el servidor apache y la autentificación de usuarios recae totalmente en el servidor apache. Esta es la opción que he usado yo.

Con respecto a la primera opción, git daemon, simplemente comentar que git push se queda colgado (llevar algo al repositorio remoto) haciéndola totalmente inútil. Parece ser un bug del cliente windows que lleva ya un tiempo ahí. La parte de servidor ssh en windows tampoco parece que se pueda poner fácilmente en un windows que no sea "server" (creo que si no es un windows "server" ni siquiera tiene servicio de ssh) y por eso me he tenido que ir a la parte de apache http.

En cuanto a las ramas, me he puesto a jugar con ello y es una pequeña maravilla. La gran mejora respecto a svn no es que haga mejor los "merge" en si mismos, supongo que el algoritmo de merge deben ser parecidos y en ambos casos, si hay conflictos, hay conflictos y se deben resolver a mano. La gran ventajas de Git sobre SVN es que Git lleva automáticamente toda la cuenta de qué ramas se han hecho de qué ramas, qué merges se han hecho y cuando hacemos un nuevo merge, el sabe automáticamente qué ficheros son los que tiene que juntar y desde dónde. SVN no lleva toda esta cuenta, por lo que el primer merge que se hace suele funcionar bien (se hace desde las revisiones adecuadas), pero si más adelante intentamos hacer un segundo merge con las mismas ramas, o de una de estas con otra, svn no sabe exactamente desde qué revisiones partir y debemos decírselo manualmente en el comando. Eso nos obliga a llevar a nosotros, manualmente, un histórico de merges que se han hecho, desde qué ramas, etc, etc. Claramente, si quieres trabajar con muchas ramas y vas a hacer muchos merges, Git es muchísimo mejor opción que Subversion.

En cuanto a facilidad de comandos, sobre todo si se está acostumbrado s Subversion, cuesta acostumbrarse un poco. El principal motivo, aparte de saber o no la sintaxis de los comandos, es que venimos de Subversion con la idea de un único repositorio central. Nuestra copia de trabajo está siempre ligada al repositorio central y los comando svn se hacen siempre contra ese repositorio central. En Git, nuestra copia del repositorio "central" es exactamente igual de importante para Git que la "central". Y pueden evolucionar por separado, yo puedo tener ramas que no están en la central y evolucionan de forma distinta, el "central" puede tener sus propias ramas, llamarse incluso igual que las nuestras, y no tener nada que ver.

El tema va incluso más allá, lo de repositorio "central" es cosa nuestra, realmente no lo hay. Git permite incluso que traigamos cosas de repositorios distintos. Puedo traerme una rama del "central", otra rama del repositorio de mi compañero de trabajo Federico y otra de internet, teniendo así un repositorio local con ramas traídas de N fuentes distintas.

Y las ramas mías y de la central, aunque se llamen igual (o no) y tengan el mismo contenido, pueden no estar ligadas para Git o pueden si estarlo. Si no están ligadas, git las considera independientes y los comandos git push o git pull no funcionarán si no les damos la paramétrica adecuada indicando ambas ramas. Si están ligadas, aunque tengan nombres distintos, git lo sabe y es capaz de ejecutar push y pull sin problemas.

Todo esto añade una complejidad excesiva de conceptos y variedad de comandos, sobre todo para los que venimos de Subversion con un respositorio central en el que están todas las ramas que existen y no hay más. Para empezar a trabajar con Git y sacarle partido a todo esto de las ramas, es necesario hacer un montón de pequeñas pruebas con los comandos para entender exactamente qué hacen, o buscar tutoriales detallados, puesto que la documentación es más bien pobre (es más una documentación de referencia que un tutorial de conceptos).

Ahora probaré el tema de servidor y autentificación con LDAP. Si consigo algo decente, montaré un servidor Git en el curro para alguno de los proyectos pequeños y empezaremos a hacer pruebas para usarlo. Me queda también ver si redmine es capaz de sacar fuentes de Git y si Hudson/Jenkins entiende de Git.

Jul 20

Sobre Git y Subversion

Este post de javahispano me ha hecho pensar de nuevo en Git. Leyendo los comentarios, llegué también a este otro donde cuentan las ventajas de Git sobre Subversion.

Hay un problema que creo que es generalizado y es que cuando se comparan dos herramientas, dos lenguajes dos entornos de desarrollo o dos lo que sea en este mundo de la programación siempre se tiende a decir que esto es mejor que aquello y que todos deberíamos usar esta herramienta. No hay nada más lejos de la realidad, cada herramienta suele tener su propósito y razón de ser, no hay cosas buenas y mejores en términos absolutos, siempre depende de cuales sean nuestras necesidades.

Mi opinión puede estar sesgada puesto que trabajo y me encuentro cómodo con Subversion, mientras que con Git sólo he hecho algunas incursiones (tengo un par de proyectos en GitHub ) y he intentado instalarme algún servidor Git en algún momento. Veamos las ventajas de Git.

Imagina, como es nuestro caso, que somos un grupo de desarrolladores (alrededor de 30) trabajando conjuntamente en proyectos, dentro de una empresa, en una sala todos juntos y con un servidor corporativo en la red interna para alojar el control de versiones (Subversion en nuestro caso). Los proyectos no son proyectos vivos, en el sentido de que el cliente pone unos requisitos, paga un precio, hay un plazo y acabado ese tiempo, el proyecto entra en mantenimiento para corregir errores, pero deja de evolucionar.

Ventajas de Git:

Es más rápido que svn en los checkouts/clone y demás comandos con accesos masivos al servidor, el repositorio ocupa menos tamaño. De acuerdo, no he hecho pruebas, pero no tengo motivos de duda.

Una vez que has hecho tu clone, puedes hacer tus commit en local, aunque no tengas acceso al servidor. Esto es una ventaja si quieres mantener tu histórico de cambios personales y que luego vaya al servidor más adelante. En nuestro caso es poco probable que no tengamos acceso al servidor, salvo que estemos trabajando desplazados. En cualquier caso, sí es una ventaja, aunque le veo una utilidad relativa en nuestro caso donde el 99% del trabajo se hace en la empresa.

Git hace mucho mejor los merges. No he probado, seguramente es cierto porque los de subversion dejan bastante que desear. En cualquier caso, nosotros no solemos hacer demasiados merges, así que en nuestro caso, nuevamente la ventaja sería relativa. Aunque claro, quizás no hagamos merges porque los merges de subversion son un infierno.

¿Y cuales son las pegas?

La primera es que nuestro servidor es windows y tiene un directorio LDAP de usuarios. He buscado tutoriales para configurar un servidor Git en Windows con LDAP y parece que es posible, pero no evidente. Git está pensado para linux y su soporte windows no es muy allá. Las ventajas que pienses conseguir con Git deberían compensar las horas de tu administrador para instalar todo eso correctamente.

Y la segunda pega es que me hace la impresión de que en general hay algo en Git que no gusta a la comunidad. El motivo es la aparición de herramientas como la mencionada en javahispano ( subgit ) o herramientas como git-svn que pretenden hacer una "mezcolanza" entre ambos repositorios. Esto hace pensar que los desarrolladores tienden a no cambiar a git (no ven suficientes ventajas o lo ven demasiado complejo) y es necesario este tipo de herramientas para animarles.

Otras pegas que me he encontrado con git es que no soporta fácilmente subproyectos dentro de un mismo repositorio ni es fácil extraer sólo la parte del repositorio que te interesa. Esta es una  molestia importante en proyectos grandes con muchos desarrolladores donde cada uno está especializado en alguna parte del proyecto. El desarrollador se ve obligado a sacar/hacer clone de todo el proyecto. Por supuesto, es una duda mía, no conozco git y es lo que he encontrado en rápidas buscas en google cuando he hecho pruebas, seguramente alguien con experiencia en git pueda decir que esto es posible y fácil.

Y finalmente, mis busquedas en google tampoco me han dejado claro si git soporta fácilmente el tema de ramas y etiquetas más allá de hacer clones del repositorio. Hacer clones no me parece una solución adecuada para ramas oficiales (por ejemplo, para tener una versión que se ha entregado al cliente y corregir sobre ella los errores que encuentre el cliente). Me obligaría a pensar en el servidor una estructura de directorios para hacer los clones y a ponerlos accesibles de alguna manera a los desarrolladores (directorios compartidos, añadir más directorios al servidor git si es que se puede, etc). Una búsqueda rápida en google sobre ramas en subversion lo deja bastante claro, dentro del repositorio se pone trunk, tags y branches y se hace svn copy. El mismo servidor subversion sin tocar nada tiene todo esto público, incluidas nuevas ramas. Insisto, no conozco git, quizás lo soporta bien pero da la impresión de que los tutoriales que digan cómo no son tan fáciles de encontrar.

Y hay otro artículo que me ha llamado la atención. De alguna forma da a entender que si lo que realmente quieres hacer es trabajar en tu proyecto y usar un repositorio distribuido como una herramienta, casi es mejor usar Mercurial. Git es más interesante, de alguna forma, se convierte más en el fin que en la herramienta, haciendo quizás  que el proyecto en el que estás trabajando sea sólo la excusa para usar Git. Git es adecuado para proyectos de gran envergadura, con múltiples ramas, con procesos de trabajo complejos y que necesitan ser configurados fuera de los estándar que ofrece Mercurial.

Soy bastante friki y me gusta/quiero pasarme a git, pero veo que tendría que tener una, dos o tres semanas libres para aprender a montar todo y organizarlo lo suficientemente bien como para hacer que todo nuestro grupo migre a git de forma cómoda, teniendo acceso a las ramas actuales con el código instalado en los clientes, la rama principal de desarrollo, etc, etc. Y la pega es que no sabría explicar claramente a los no frikis qué ventajas reales van a tener con una única excepción. Si varios desarrolladores se van un período largo a las instalaciones del cliente a desarrollar, pueden montar fácilmente su propia red de repositorios git entre ellos para corregir bugs, hacer merges entre ellos y cuando estén de vuelta, hacer un merge en el repositorio oficial.

Pero resumiendo, posiblemente Git sea bueno para proyectos opensource con muchos colaboradores, donde se hacen muchas ramas experimentales, muchos desarrolladores cada uno a su bola intenta hacer mejoras, se quiere juntar todo con cierta frecuencia, etc. Es decir, proyectos vivos, complejos y con muchos desarrolladores más o menos independientes. Para un proyecto de empresa que requiere un repositorio central con la versión oficial del cliente, donde los desarrolladores están todos ubicados en la misma sala y no tienen tanta libertad para sus desarrollos porque deben limitarse a requisitos concretos en plazos de tiempo concretos, quizás Subversion es más que suficiente.