Fusiones en Git: Merge y Rebase


01 Introducción

Cuando un usuario utiliza Git, tarde o temprano, debera utilizar ramas, que son un conjunto de commit en una línea de tiempo.

El esquema clásico de desarrollo con ramas en un repositorio de Git, es tener una rama principal, denominada master, donde tendremos código de forma estable, y conjunto de ramas con diferentes nombre como desarrollo o hostfix, que se utilizaran para el desarrollo de código.

En algún momento debemos unir las ramas. ya sea entre varias ramas de desarrollo o de una rama desarrollo con la rama master. Este proceso se denomina fusión o merge. Que consistira en mover un conjunto de commit desde una rama a otra.

Existen varios formas de hacer de fusionar dos ramas, el resultado será el mismo. La diferencia sera en como lo hace.

Principalmente tendremos dos formas de realizar fusionar ramas.

02 Merge

Tenemos dos ramas, por ejemplo rama master y desarrollo, queremos fusionar la rama desarrollo sobre la rama master

Nos situamos en la rama hacia donde se dirige la fusión, en este caso la rama_master_, y realizamos el merge.

	git checkout master
	git merge desarrollo

Esta fusión realiza una “mezcla” , genera un nuevo commit con el contenido de la rama desarrollo en la rama master.

Ahora podemos borrar las rama desarrollo o seguir utilizandola para seguir desarrollando código.

03 Rebase

Es el otro tipo de fusión con un funcionamiento diferente, aunque tiene el mismo resultado. Este tipo de fusión lo que realiza es reorganización de los commits.

Por ejemploi, tenemos las dos ramas del ejemplo anterior, master y desarrollo.

Realizamos el mismo proceso anterior, fusionar la rama desarrollo en la rama master.

Cuando ejecutamos un rebase, nos debemos situar en la rama que vamos a fusionar, al contrario que ocurria con el merge. Y ejecutamos.

git checkout desarrollo
git rebase master

Este comando mueve todos los commit de la rama desarrollo a continuación de la rama master, el resultado sería.

El resultado es un historial de commit mas limpio.

En el proceso de reorganización, a los commits se le ha asignado un nuevo identificador (hash). En algunos escenario, repositorios públicos, no es aconsejable utilizar rebase,

Cuando realizas un push descargas commits a tu repositorio local, si realizas un rebase, modificas los id de los commit, si realizas un pull estos commits, con sus identificadores cambiados, se subiran al repositorio público. Si otro desarrollador realiza un pull, obtendra un conjunto de commit con los id cambiado, que se integraran en su repositorio local y provocara muchos dolores de cabeza.

04 Rebase interactivo

Es una opción de Rebase y permite realizar la reorganización de una forma manual. Continuando con el ejemplo anterior, si ejecutamos.

git rebase -i desarrollo

Se nos abrira el editor que tenga configurado Git, por defecto vi, mostrando todos los commit de la rama desarrollo.

En la parte superior veremos los commit con sus identificadores, y una opción que indica la acción que vamos a realizar sobre ese commit.

Entre las acciones que podemos realizar tenemos:

  • pick: Sin modificación , no realizamos acción sobre ese commit.
  • squash: Permite unir commits, el seleccionado con el anterior. El commit debera tener un nuevo mensaje.
  • fixup: Permite unir commit, utilizando el mensaje del primero.
  • edit: Para editar el mensaje del commit.
  • drop: Borra un commit, también eliminado la línea directamente.
  • exec: Permite ejecutar un comando usando shell.

También podemos escoger un conjunto de commit, no toda la rama, para reorganizar. Como ejemplo.

git rebase -i master~3

Selecciona los útimos 3 commits de la rama master para reorganizar.

05 Conclusión

Normalmente se usa merge para fusionar dos ramas, pero el comando rebase debido a su limitación de no usarse en repositorios públicos, no es tan común, aunque tiene su utilidad para dejar un historial mas limpio.

El comando rebase interactivo es muy útil para limpiar aquellos commit que no aportan valor al historial, se pueden unir con otros, modificar su mensaje. Es un comando muy útil para que el historial de una rama sera mas comprensible.