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.

Sep 09

Hooks en subversion

Hace ya un par de años que me convertí en el administrador del repositorio de subversion de nuestro departamento. Incluso prestamos servicio de subversion a otros departamentos para sus proyectos.

Uno de los problemas que me he encontrado es que la gente por despiste, por "pasotismo"  o por no saber dónde guardar las cosas, mete en subversion ficheros binarios (.exe, .dll, etc) documentos (.doc, .docx, .pdf), etc, etc que no es el sitio adecuado para guardarlos, además que abusar de ello puede llenar el disco en un pis-pas. Y no es un problema específico de un administrador de subversion, pero tampoco me gusta que la gente suba a subversion sin poner el correspondiente comentario en el commit.

Así que me puse a investigar cómo evitarlo y descubrí los "hooks" de subversion. Son scripts que se guardan en el servidor y que se ejecutan cuando ocurren ciertas acciones en subversion, como un commit, un bloqueo, etc.

En el directorio /path/REPOSITORIO_SVN/hooks de un proyecto basta con poner un script de nombre pre-commit.bat (en windows también vale un pre-commit.exe o pre-commit.com, para unix bastaría un fichero de nombre pre-commit, sin extensión, con permisos de ejecución) que se ejecutará siempre que se intente hacer un commit y se ejecutará antes del commit, pudiendo rechazarlo en un momento dado. Ese directorio ya está lleno de scripts con extensión .tmpl, no ejecutables por tanto. Cada uno corresponde a uno de los posibles "hooks" y nos bastaría con copiarlo poniendo extensión .bat (o dándole permisos de ejecución en linux) y modificarlo por dentro para que haga lo que queramos.

Este script debe salir de forma normal (exit 0) si el commit se acepta, y salir con error (exit 1) si no se acepta el commit. En este último caso, lo que el script saque por la salida de error estándar, será lo que subversion le muestre al usuario como mensaje de error.

El que yo he puesto, pre-commit.bat, verifica las extensiones de los ficheros que se quieren subir y verifica que hay un comentario. El script es el siguiente y me disculpareis si hay forma mejor de hacerlo (seguro que la hay), pero se más bien nada de "scripts" en windows.

 

set REPOS=%1
set TXN=%2
svnlook changed %REPOS% -t %TXN% | findstr ".\exe \.dll \.o \.lib \.a \.so \.jar \.class \.doc \.docx \.pdf \.zip" >&2
if %errorlevel% equ 0 (goto err)
 
svnlook log %REPOS% -t %TXN% | findstr . > nul
if %errorlevel% gtr 0 (goto err2)
 
exit 0
 
:err
echo No se admiten ficheros binarios >&2
exit 1
 
:err2
echo Como no metas un comentario …. >&2
exit 1

 

Como parámetros del script, subversion nos pasará el repositorio y una "cosa extraña" que contiene la información de lo que se está pretendiendo meter. Nos guardamos esos dos parámetros %1 y %2 en las variables REPOS y TXN.

El comando de subversion svnlook, pasándole estas dos cosas, es capaz de darnos información sobre el commit. Así, svnlook changed nos da un listado de los ficheros que se pretenden modificar/añadir/borrar. svnlook log nos da el comentario del commit.

El comando findstr de windows nos permite buscar una cadena. En el primer uso buscamos extensiones de ficheros no permitidos. En el segundo caso, buscamos cualquier caracter (el punto de findstr equivale a cualquier caracter). Este comando findstr da un error si no encuentra la cadena, por lo que inmediatamente detrás pongo un if de %errorlevel% (que es donde se guarda si ha habido error) para decidir si se acepta el commit (exit 0) o saco algún error.

En fin, las posibilidades serían muchas, como verificar si el comentario lleva un número de incidencia para admitirlo, analizar el contenido del fichero que se va a meter buscando cosas no permitidas (código sin comentar, que no cumpla métricas, paths absolutos dentro, etc) o incluso ¿por qué no? si compila o no compila y pasa los test.

Jun 04

Migrando a Subversion

 

¡¡ Por fin tenemos nuestro primer proyecto migrado a subversion !!.

La historia ha sido una verdadera odisea. Normalmente usamos CVS, pero en el momento de empezar a trabajar con ramas un poco en serio, el tema se hacía demasiado pesado. CVS crea las ramas recorriendo todos los ficheros del repositorio y marcando la rama para cada uno de ellos. Crear una rama en CVS tardaba cerca de media hora en cada proyecto implicado. Subversion, al tener todo el repositorio con un número de versión único, no necesita recorrer todos los ficheros uno a uno para hacer la rama, le basta con marcar en algún sitio que en ese número de versión comienza una rama. Tarda como la mitad de medio segundo (es un decir) en hacer la rama de un repositorio, independientemente de la cantidad de ficheros que haya almacenados.

Por otro lado, nuestro servidor de CVS se estaba quedando "viejito". Una estación solaris del año del "catapúm" con 128 megas de ram (al que hace poco se le estropeo un módulo de 64 y creo que de esos ya no hay ni el rastro), con el disco duro (de pocos gigas) permanentemente al 99%. Total, que se imponía también un cambio de máquina.

Así que aprovechando lo uno con lo otro, decidí que nos pasabamos a Subversion en un servidor nuevo. Dicho….. y a esperar.

Primero convencer a la gente de las excelencias de Subversion sobre CVS. Como siempre, a unos pocos les parece estupendo, a muchos les importa tres pepinos y a algunos lo de "¿Para qué vamos a cambiar si ahora funciona?". A base de dar la paliza, conseguí convencer (o al menos dejaron de protestar) a todos.

Después lo de conseguir el servidor nuevo. Ni el departamento ni los proyectos para los que trabajamos estaban dispuestos a comprar un servidor (pensé seriamente en ir a tomar los cafés encima del servidor actual, para que ocurriera "una desgracia"). Así que a negociar con el departamento de informática de la empresa, a ver cuánto nos cobran por darnos un subversion en uno de sus servidores. Tras mucho tira y afloja (y sobre todo gracias a la persona que nos hizo de intermediaria en la software lab con la que trabajamos), nos dieron el subversion gratis. Entre pedir el servidor a los proyectos, intentar convencerles y hablar con el departamento de informática pasaron casi dos meses.

Y hoy, por fin, la primera migración. Me bajé el cvs2svn e intenté migrar uno de nuestros proyectos. Desgraciadamente, intenté hacerlo sobre windows y no hubo manera. Tenía el cygwin y teóricamente todo lo necesario, pero me fallaba en un punto en el que se hace una llamada al comando "sort". El de windows no vale, porque funciona distinto del de unix. El de cygwin aparentemente me daba problemas porque se liaba con las \ de los directorios (al ser unix, espera / de directorio). Me bajé los UnxUtils, pero al ejecutar el comando sort daba un error muy raro (insuficiente espacio en disco, o algo así, habiendo más de 20 Gigas libres). Así que reinicié el ordenador para arrancar en linux y ahí fue todo rodado a la primera.

Total, ya tenemos nuestro primer proyecto en subversion. El primero de una larga lista de ellos que debemos ir migrando poco a poco.

Nov 21

Apaches como setas

 

Ultimamente me ha dado por probar algunas herramientas nuevas e incluso volver a probar algunas que ya había probado. En concreto, me he vuelto a instalar un servidor de subversion, he vuelto a intentar instalar trac, también otra cosa que he encontrado por equivocación y que se llama traks (una aplicación web para usar GDT, con lo cual me resultó interesante), etc, etc.

Como soy vago y encima estoy mal acostumbrado a Windows, para todas ellas me he buscado instaladores de windows, de esos que se instala todo solo con un par de clicks. En concreto, he usado los instaladores de bitnami, u otros del estilo, cuya principal ventaja es que con un par de clicks instalan TODO lo necesario para tener la aplicación funcionando.

Y la ventaja de estos instaladores es precisamente su problema.

Casi todo lo que he instalado son aplicaciones web, así que creo que tengo todos los puertos desde el 8080 al 9999 ocupados con servidores apache, cada uno para su aplicación. Debo tener como tres o cuatro versiones de python instaladas en distintos directorios (que además ya tenía instaladas previamente), varios servidores MySql y sabe Dios cuántas cosas más por tripitido.

Menos mal que después de probada un poco la aplicación, se desinstala igual de fácil que se ha instalado.

Por cierto, los tra* no me van bien. trac me sigue pareciendo demasiado complejo de configurar sin el instalador, aparte de que me da errores al ejecutar los python. Y el bitnami stack de track, después de la instalación, me ha fallado en el arranque, por lo que no he podido siquiera verlo en marcha.

Nov 12

Más de Subversion

Hace poco me tocó hacer una rama CVS de los proyectos para estabilizar una versión para unas pruebas con el cliente. Ya se sabe, rama del repositorio del proyecto y rama de todos los repositorios con librerías que utilice el proyecto.

Pues bien, ha sido horrible. Son cuatro o cinco repositorios y cada uno de los proyectos/librerías a "enramar" tienen fácilmente tres mil ficheros java. Eché toda la tarde en hacer las dichosas ramas. Primero un update, luego el cvs tag para poner una etiqueta justo en el punto donde comienza la rama y luego el cvs tag -b para crear la rama. Al hacerlo CVS fichero a fichero, media hora larga con algunos de los repositorios mientras cvs hace el trabajo.

Se me ocurrió, harto de ello, montar un servidor de subversion, migrar alguno de los repositorios CVS a subversion (usando cvs2svn) y mirar a ver cuánto tarda subversion en hacer la rama (svn cp). Es casi inmediato, ya que realmente no realiza la copia real de todos los ficheros (lo hará cuando se vayan modificando si se van modificando) y tampoco tiene que andar recorriendo todos los ficheros para ver su versión actual (CVS tienen un número de versión para cada fichero, mientras que subversion tiene un único número para todo el repositorio).

Todo el mundo habla que los sistemas de control de versiones distribuidos, estilo Bazaar o Git son maravillosos. También se habla mejor de Subversion que de CVS, aunque no todos lo hacen. A mí realmente todo eso me parece bien, pero mientras no veo una necesidad real o una mejora importante, no veo tampoco necesidad de cambiar. Ahora sí he encontrado un motivo, así que es cuestión de empezar a mirar en serio la posibilidad de migrarlo todo a Subversion.

De momento descarto Bazaar o Git por tener menos soporte para los IDEs habituales (eclipse en concreto). Tampoco tengo muy claro lo veloz que puede ser hacer un branch de un repositorio grande si eso implica la copia completa de todo el repositorio, con su historia (ya digo, repositorios de tres mil clases java con cuatro o cinco años de historia y alrededor de veinte desarrolladores de media desarrollando día a día).