Una de las características mas interesantes, sin lugar a dudas, del control de versiones, son las ramas o ramificaciones. Se trata de una característica que resulta realmente interesante y que nos permite hacer variaciones de nuestro proyecto sin perder el enfoque de nuestro objetivo final. De ahí que la gestión de ramificaciones en los sistemas de control de versiones sea algo fundamental.
Como ya comenté en el artículo de introducción a Git, y no me cansaré de insistir, los sistemas de control de versiones no son algo exclusivo de los desarrolladores, sino que cualquier profesional puede, y debería, hacer uso de ello. Y es precisamente en la gestión de ramificaciones donde adquiere su mayor relevancia.
Así, por ejemplo, un escritor, haciendo uso del sistema de control de versiones y de las ramificaciones, puede crear varias versiones de un mismo capítulo, continuar con su libro hasta el final y, en ese momento, decidir cuál de las ramificaciones es la más interesante. Lo mismo podemos decir de un dibujante, un diseñador gráfico o cualquier otra disciplina digital.
¿Cómo hace Git la gestión de ramificaciones?
Gestión de ramificaciones con Git
Como he comentado en la introducción, la gestión de ramificaciones es parte fundamental de cualquier sistema de control de versiones, permitiéndonos seguir diferentes caminos de forma simultánea para alcanzar el objetivo final.
De esta manera podemos añadir nuevas características a nuestro proyecto, ya sea un libro, una imagen o una aplicación… y ver el resultado. Una vez comprobado cómo ha quedado cada una de estas ramas en nuestro proyecto, fusionaremos cada una de las ramas con la rama principal.
Crear una nueva rama
Así, para crear una rama de nuestro proyecto, tan solo tenemos que ejecutar la siguiente orden:
git branch nueva_rama
Cambiando de rama
Para cambiar de esa rama principal a la rama nueva_rama
, ejecutaremos la orden:
git checkout nueva_rama
Y si queremos volver a nuestra rama principal, de nuevo, ejecutaremos la orden:
git checkout master
¿En qué rama estamos?
Llegados a este punto, suponiendo que has creado varias ramas y estás trabajando en todas ellas de forma simultánea, por ejemplo probando diferentes técnicas para dar respuesta a un determinado bug, ¿como podemos saber en qué rama nos encontramos?
La solución se encuentra en ejecutar la orden:
git log --oneline
Este nos mostrará un puntero denominado HEAD
que es el que nos señala dónde nos encontramos. Como muestra, en este ejemplo, al ejecutar la orden git log --oneline
vemos el puntero HEAD
en la rama master
.
Si ahora cambiamos de rama git checkout http_connection
y volvemos a ejecutar la orden git log --oneline
, el resultado es el siguiente:
Si comparas las dos capturas de pantalla, te darás cuenta de que hemos vuelto hacia atrás. En el primer HEAD
apuntaba al commit
612b1cf
, mientras que en la segunda captura de pantalla HEAD
apunta a un commit
anterior, el a2b8930
.
¿Qué podemos hacer en cada rama?
En cada rama trabajaremos normalmente, como hacemos cuando estamos en la rama principal master
. Nuestro procedimiento de trabajo es el habitual:
- añadimos, borramos o modificamos archivos.
- confirmamos los cambios realizados en nuestra rama ejecutando la orden
git add .
- realizamos el
commit
ejecutando la ordengit commit -m "cambios realizados"
.
Todos estos cambios se realizan en la rama en la que nos encontramos, sin afectar al resto de ramas. De esta forma, si cambiamos a otra rama, no encontraremos esos cambios.
Una vez realizados todos los cambios necesarios en nuestra ramificación, y considerado que ésta ya es adecuada para pasarla a producción, ha llegado el momento de realizar la fusión. ¿Cómo hacemos este paso?
Fundiendo ramas
Para fundir una rama con la rama principal master
o con cualquier otra rama, tenemos que proceder como sigue:
- nos movemos a la rama con la que queremos fundirnos.
Por ejemplo, si queremos fundir nueva_rama
con la rama master
nos desplazaremos a la rama master
, ejecutando la orden git checkout master
.
- realizamos la mezcla ejecutando la orden
git merge nueva_rama
En general es tan sencillo como lo que acabo de comentar, salvo que haya conflictos en la fusión.
Conflictos de fusión
Para comprender esto de los conflictos de fusión vamos a partir de que tenemos nuestra rama principal master
y una rama derivada nueva_rama
. Cuando nos decidimos a realizar la fusión hemos realizado cambios tanto en la rama derivada nueva_rama
como en la rama principal. Sin embargo, las modificaciones realizadas en la rama principal se efecturaron posteriormente a haber realizado la ramificación.
En este caso, si hay cambios que afectan a un mismo archivo se producirá un conflicto. El sistema de control de versiones no sabrá que hacer, que parte del código o del archivo prevalecerá, si la correspondiente a la rama principal, o la correspondiente a la ramificación nueva_rama
.
En el ejemplo anterior, he modificado un artículo tanto en la rama principal master
como en la ramificación articulo5_opcion1
. Cuando la he fusionado con la rama principal master
, me indica que hay conflictos y es necesario resolverlos.
Resolviendo conflictos
El primer paso es averiguar dónde están los conflictos que nos impiden concluir la fusión. Para ello, ejecutaremos la orden git status
, tal y como puedes ver en la siguiente captura de pantalla:
Vamos a editar articulo5.md
, utilizando nano
por ejemplo. El contenido del archivo en este caso será el siguiente:
<<<<<<< HEAD Esta es la modificación que he realizado en la rama principal después de haber realizado la ramificación ======= Esta es la opción 1 >>>>>>> articulo5_opcion1
Efectivamente esto es una combinación de la rama principal master
y de la ramificación articulo5_opcion1
. Debemos modificar el archivo, hasta dejarlo como deseamos. Una vez terminada nuestra edición, procedemos como de costumbre:
git add . git commit
Ahora ya podemos ver el resultado, ejecutando la orden, git log --oneline --graph --all
, en la siguiente captura de pantalla:
Conclusiones
Hasta aquí hemos visto todo lo necesario para crear y fusionar ramas. Con esto ya te puedes hacer una idea del potencial del control de versiones y sobre todo del potencial de las ramificaciones. Y como he comentado e insistido en la introducción, no se trata de algo exclusivo para los desarrolladores de aplicaciones, sino que se puede utilizar en cualquier campo.
En el próximo artículo incidiremos más en la gestión de ramas y ramificaciones y veremos la forma más correcta de trabajar con ramificaciones y algunas herramientas.