Da igual que seas desarrollador backend o frontend o diseñador web, el control de versiones es un aspecto que debes aprender para trabajar de forma profesional. En este artículo vemos una introducción a Git, uno de los sistemas más populares.
Es probable que últimamente hayas visto que se habla mucho de Git y del control de versiones. Si te dedicas más al diseño web y menos al desarrollo o a la maquetación web es probable que no le hayas prestado mucha atención, que hayas pensado que eso no es para ti. Con este artículo quiero hacerte cambiar de idea. Tienes mucho que ganar si aprendes a usarlo. Prometo no usar aquí (casi) ningún comando.
Existen aplicaciones que nos ofrecen interfaces gráficas para trabajar con Git. Yo uso SourceTree y todos los ejemplos de este artículo son de este programa.
Qué es Git
Empecemos por el principio. Git es un sistema de control de versiones que almacena los cambios que se producen en los archivos de un proyecto de manera que puedas recuperar una versión concreta en el futuro. Para ser exactos no guarda los cambios, las diferencias, sino que hace capturas completas, como si fueran fotografías, de los archivos que modificas.
Las ventajas son muchas:
- tienes un histórico de los cambios de un proyecto
- imprescindible para trabajo en equipo: varias personas pueden trabajar a la vez en el mismo archivo sin que el trabajo de uno machaque el trabajo de otro
- hacer experimentos sin miedo: con el uso de ramas podrás crear versiones de tu proyecto para experimentar y volver a la última versión estable tan fácilmente que te vas a reír. Te puedes hacer una idea de la tranquilidad que da esto.
Instalación
Uno de los puntos que frena a muchos diseñadores es el proceso de instalación, que no te asuste lo que hayas podido leer sobre teclear un montón de comandos de terminal o procesos complejos de configuración… No tires la toalla tan pronto. El proceso es realmente sencillo, tienes instrucciones muy claras de cómo hacerlo aquí (el objetivo de este artículo es mostrarte la utilidad de usar Git y la filosofía que hay detrás, así que los pormenores técnicos los voy enlazando para no desviarnos de nuestro objetivo). Incluso puede que ya lo tengas instalado en tu ordenador (si tienes Xcode, por ejemplo).
Para saber si ya lo tienes instalado puedes abrir una ventana de Terminal y escribir
Como vamos a usar SourceTree como interfaz gráfica tenemos la ventaja de que este programa trae incorporada su propia versión de Git, por lo que puedes obviar el paso de instalar Git en tu sistema si no lo tienes ya.
Empezando un proyecto
Con Git ya instalado espero que estés con ganas de empezar a darle caña. Lo primero es decirle que empiece a gestionar un proyecto.
Abrimos SourceTree y en la ventana de Bookmarks hacemos clic en el icono de Nuevo Proyecto. Nos aparece una ventana emergente con varias opciones:
- Clonar: para copiar un repositorio existente
- Añadir un proyecto existente
- Crear un nuevo repositorio
Debemos elegir la última opción. Un repositorio es simplemente un directorio en nuestro ordenador que contiene los archivos de un proyecto que queremos controlar.
Si el directorio elegido ya tiene archivos, tendrán el estado not tracked (no están en seguimiento). Tendremos que decirle a Git que inicie el seguimiento de estos archivos.
Para que Git empiece a observar estos archivos los añadimos al staging area (área de preparación) marcando la casilla correspondiente. Así vemos cómo pasan de la sección Unstaged files a Staged files.
Este es el paso previo a confirmar los cambios: a hacer un commit, si hablamos en términos de Git.
Ahora solo nos queda escribir un mensaje de confirmación (commit message) que, en esta fase, suele ser ‘Initial commit’ pero puedes escribir lo que quieras. Al hacer commit le estaremos diciendo a Git que queremos que guarde todos esos archivos con su contenido actual, que tome una «fotografía» del proyecto. Cada commit es una marca en la historia del proyecto, una señal en un mapa.
Después de esto veremos que no tenemos nada más que confirmar (Nothing to commit). ¡Bravo! Nuestra área de trabajo (working copy) está limpia, todos los archivos de nuestro proyecto se encuentran en su versión más moderna.
Gestionando archivos modificados
Cuando trabajemos y modifiquemos algún archivo, SourceTree nos mostrará un listado de los archivos pendientes. Un archivo pendiente puede estar ser de dos tipos: un archivo que ya estaba añadido al repositorio y ha sido modificado y un archivo nuevo que no estaba en el repositorio (untracked).
Imaginemos que hacemos algún ajuste en nuestro CSS, editamos el archivo correspondiente .scss y se actualiza el compilado .css. Entonces veremos que tenemos dos archivos pendientes.
Seleccionamos estos dos archivos y los añadimos al stage area (área de preparación). En la caja de texto del commit escribiremos algo así como: «Cambios en el CSS». Hacemos commit y listo. Ahora tenemos dos commits, dos fotografías del proyecto. La primera (initial commit) que hicimos al iniciar el proyecto y otra con dos archivos modificados.
Este es el proceso que haremos cada vez que el proyecto cambie. ¿Cuándo conviene hacer commit? Una pregunta interesante que no tiene una única respuesta correcta. Cada diseñador tiene sus criterios. Yo suelo hacer commit cada vez que considero que tengo algo acabado: un formulario, la cabecera, una galería… Así los commits son descriptivos y concretos. Es muy importante que dediques un poco de tiempo a la hora de escribir los mensajes de los commits, que sean claros y con todo el detalle que necesites para identificar esa «señal en el mapa».
También hago un commit al final del día de trabajo por seguridad. Puede que una tarea se prolongue durante varios días y no tenga nada «cerrado» un día concreto pero me gusta hacer commit para tener una copia de seguridad del trabajo realizado para evitar desastres.
Cada vez que hacemos un commit de una serie de archivos modificados creamos un nuevo punto en nuestro mapa y avanzamos el puntero de Git (HEAD) un paso. Este comportamiento es el comportamiento habitual en un proyecto sencillo. Vamos trabajando y vamos avanzando hacia adelante. Ahora veremos cómo podemos tomar una bifurcación en el camino para continuar por otro lado.
Ramas
Es hora de jugar un poco.
Una rama es una bifurcación, en lugar de avanzar el puntero de Git hacia adelante decidimos que tomamos otra ruta, otro camino. Al hacer esto podemos trabajar en dos versiones de nuestro proyecto a la vez. Es genial para hacer pruebas, experimentos, sin miedo a que afecte a lo que ya tenemos hecho del proyecto.
Imaginemos que nuestro cliente ha cambiado su imagen corporativa en mitad del desarrollo de su sitio web (¡de locos pero es un ejemplo!). En lugar de un precioso y hipster naranja desaturado ahora el color principal es un verde lima electrizante.
Como sospechamos que el cliente es un poco caprichoso y puede que cambie de idea cuando vea el nuevo color, vamos a probar estos cambios en una nueva rama para desecharla sin miedo en caso de que sea necesario.
Crear una rama es muy sencillo, seleccionamos la rama desde la que vamos a partir (generalmente desde la rama principal que suele llamarse master) y hacemos clic en el botón «Branch». Tendremos que darle un nombre. Una vez más, cuanto más descriptivo, mejor. En este caso la llamaríamos “nuevo-esquema-color”, por ejemplo.
Git moverá entonces su puntero a esta rama. En este momento las dos ramas existentes se encuentran en el mismo punto porque no hemos hecho aún ningún cambio.
Como somos unos desarrolladores front-end muy aplicados y usamos Sass tenemos todo definido en variables. Así que abrimos nuestro archivo _variables.scss y cambiamos $primarycolor: $naranjadesaturado; por $primarycolor: $verdelima; Compilamos con Codekit y vamos a SourceTree a ver qué nos dice Git que ha cambiado.
Voilà! Encontramos dos archivos modificados: _variables.scss y el recién compilado screen.css.
Llevamos estos archivos al stage area como vimos más arriba y hacemos commit. Este commit hace que la rama “nuevo-esquema-color” avance un paso.
Si cambiamos el puntero de lectura de Git (HEAD) a la rama master (hacer checkout) volveremos al estado anterior y no veremos ni rastro del color verde lima. Para que nos entendamos, hacer checkout no es otra cosa que mover el puntero de Git a una rama.
Mejor volvamos a la rama en la que estamos trabajando (“nuevo-esquema-color”). Si estamos contentos con el trabajo de nuestra rama, es hora de integrarlos en la rama principal (master). Esta acción recibe el nombre de merge (fusionar). El proceso es muy sencillo:
- llevamos el puntero de Git a la rama master (checkout)
- fusionamos los cambios de nuevo-esquema-color en master (merge nuevo-esquema-color into master).
Ahora ambas ramas vuelven a estar sincronizadas. Una vez que acabo con una rama, y la he integrado en master, suelo borrarla para mantener limpio el proyecto. A lo mejor tú prefieres conservarlas todas.
Nuestro proyecto en remoto
Todos los procesos de Git ocurren en local, en nuestro ordenador. No obstante, podemos usar servicios como GitHub o BitBucket para alojar una copia de nuestros proyectos en remoto. Esto es genial para tener una copia de seguridad en remoto y es imprescindible para trabajar en equipo. Cada persona del equipo puede subir sus commits al mismo repositorio en remoto. SourceTree, el cliente de Git que estamos usando está desarrollado por Atalassian, los creadores de BitBucket que es el servicio que yo uso (permite repositorios privados ilimitados). De todas formas SourceTree conecta también con GitHub.
No voy a entrar en detalles de cómo conectar SourceTree con un servicio remoto, es muy sencillo, básicamente: nos damos de alta en BitBucket, introducimos los datos del usuario que hemos creado en SourceTree y desde nuestro repositorio en local, en Ajustes, creamos el repositorio remoto.
Cuando confirmemos cambios en local podemos hacer push que no es otra cosa que subir estas confirmaciones al repositorio remoto.
Para comprobar si hay actualizaciones en el proyecto alojado en BitBucket hacemos fetch y pull para descargar los últimos cambios y mantener actualizado nuestro repositorio local.
Conflictos. ¡Oh, no!
A veces durante el proceso de fusionar dos ramas pueden aparecer conflictos. No te asustes, siempre puedes deshacer la fusión y «no romper nada». Un conflicto ocurre cuando un mismo archivo presenta contenido diferente en un mismo punto. Git nos avisa y señala en qué punto hay un conflicto, añadiendo un código con este formato:
Línea de texto en la rama activa
===============
Línea de texto en la rama nuevo-esquema-color
>>>>> nuevo-esquema-color
Como puedes ver hay dos bloques separados por =====. La parte superior pertenece a la rama que tenemos activa, en nuestro ejemplo sería master que es en la que queremos integrar los cambios de la rama nuevo-esquema-color, que es el contenido del bloque inferior. Podemos editar ese archivo con cualquier editor y borrar la parte que no queremos mantener o usar una aplicación específica para la resolución de conflictos. Cuando hayamos acabado solo tenemos que guardar el archivo y añadirlo al área de preparación (staging area), el conflicto quedará resuelto.
El final, solo el principio
Espero que hayas llegado hasta el final, si es así, enhorabuena.
Este artículo es una introducción a los aspectos esenciales de Git. Su objetivo principal es que veas lo útil que es y que le pierdas el miedo o el respeto. Con un poco de práctica verás lo sencillo y hasta intuitivo que es hacer todos estos procesos. Muy pronto te preguntarás cómo has podido trabajar sin un control de versiones.
Hay mucho más: enviar a producción desde una rama de un repositorio, hacer pull requests, clonar proyectos de terceros…
Recursos
- SourceTree, cliente gráfico para Git
- BitBucket, para alojar los repositorios en remoto
- GitHub, también para alojar tus repositorios en remoto, el sitio de referencia para proyectos open source
- Pro Git, traducción del libro clásico de Git