Apéndice: Diferencia entre git merge y git rebase

5 min

Contexto

En este ejemplo tenemos un repositorio con una rama principal main que contiene un archivo de base fichier1.txt y un primer commit inicial. A partir de main creamos dos ramas, branche1 y branche2, cada una destinada a probar respectivamente rebase y merge. Después se crean dos ramas de trabajo adicionales, branche-rebase desde branche1 y branche-merge desde branche2, para añadirles modificaciones.

Historial inicial

El proyecto empieza con un repositorio que contiene un solo commit en main, correspondiente a la creación del archivo fichier1.txt:

plaintext
(main)
A               # Commit inicial con fichier1.txt

En el commit A hemos añadido el archivo fichier1.txt con contenido inicial.

A continuación se crean dos ramas nuevas a partir de main:

  1. branche1: destinada a acoger branche-rebase para probar git rebase.
  2. branche2: destinada a acoger branche-merge para probar git merge.

Trabajo en cada rama de trabajo

En cada rama de trabajo (branche-rebase y branche-merge) hacemos tres commits distintos. Estos son los commits en detalle para cada rama:

plaintext
(main)
A

(branche-rebase)
       \
        D---E---F   # Commits añadidos en branche-rebase

(branche-merge)
       \
        G---H---I   # Commits añadidos en branche-merge
  1. Commits en branche-rebase:

    • Commit D: creación del archivo fichier-2-rebase.txt con el contenido inicial "Modification 1 dans branche-rebase".
    • Commit E: adición de "Modification 2 dans branche-rebase" en el mismo archivo fichier-2-rebase.txt.
    • Commit F: adición de "Modification 3 dans branche-rebase" en el mismo archivo fichier-2-rebase.txt.
  2. Commits en branche-merge:

    • Commit G: creación del archivo fichier-2-merge.txt con el contenido inicial "Modification 1 dans branche-merge".
    • Commit H: adición de "Modification 2 dans branche-merge" en el mismo archivo fichier-2-merge.txt.
    • Commit I: adición de "Modification 3 dans branche-merge" en el mismo archivo fichier-2-merge.txt.

Estos commits añaden contenido idéntico, pero en archivos distintos (fichier-2-rebase.txt y fichier-2-merge.txt), para permitir una comparación clara entre merge y rebase.


Paso 1: fusión de branche-merge en branche2 con git merge

Para integrar las modificaciones de branche-merge en branche2, usamos el comando git merge en branche2. Esta operación crea un commit de fusión que conserva un historial completo e incluye los commits de la rama de trabajo sin reorganizarlos.

El historial después del merge:

plaintext
(branche2)
A-------J        # J es el commit de fusión
 \       |
  \      |
   G---H---I     # branche-merge conserva su historial distinto
  • Explicación de los commits:
    • Commit J: commit de fusión que combina el contenido de branche2 con las modificaciones de branche-merge (G, H, I) sin desplazarlos ni cambiar su orden.
  • Observación: con git merge, el historial muestra un "punto de unión" que indica visualmente dónde se fusionó branche-merge en branche2. Eso conserva un historial completo y distinto para cada rama, a menudo útil en proyectos colaborativos.

Paso 2: integración de branche-rebase en branche1 con git rebase

Para integrar las modificaciones de branche-rebase en branche1, usamos el comando git rebase. A diferencia de merge, rebase recoloca los commits (D, E, F) de branche-rebase como si se hubieran creado después del último commit de branche1 (A).

El historial después del rebase:

plaintext
(branche1)
A---D'---E'---F'   # Commits de branche-rebase reaplicados al final de branche1
  • Explicación de los commits:
    • Commits D', E', F': commits reproducidos de branche-rebase aplicados de forma lineal a continuación de A en branche1.
  • Observación: con git rebase, los commits de branche-rebase se reorganizan para formar un historial lineal sin "punto de unión", como si se hubieran añadido directamente después del commit inicial A. Eso simplifica el historial y lo deja más limpio, pero puede ocultar el recorrido de las ramas de trabajo iniciales.

Comparación final

Las diferencias observadas en los logs de Git permiten entender mejor los usos específicos de merge y rebase.

  • git merge:

    • Efecto: mantiene un historial completo con un commit de fusión que marca la unión de las ramas.
    • Ventaja: ideal para seguir un historial completo en proyectos colaborativos, porque cada unión es visible.
    • Inconveniente: el historial puede volverse complejo con muchas uniones, sobre todo en proyectos con varias ramas.
  • git rebase:

    • Efecto: reorganiza los commits para colocarlos de forma lineal al final de la rama principal, sin crear un commit de fusión.
    • Ventaja: ideal para un historial lineal y limpio, al minimizar las uniones. Suele preferirse en proyectos pequeños o para limpiar el historial antes de compartirlo.
    • Inconveniente: puede ocultar el recorrido de las ramas de trabajo, lo que puede ser un problema si varias personas trabajan en las mismas ramas.

Resumen

ComandoHistorialCaso de uso ideal
git mergeHistorial completo con punto de uniónProyectos colaborativos con varias ramas
git rebaseHistorial lineal sin puntos de uniónLimpieza del historial antes de un merge compartido

En resumen:

plaintext
git merge   ->  Historial completo con commit de fusión
git rebase  ->  Historial lineal sin commit de fusión

Esta guía te permite entender y visualizar las diferencias entre git merge y git rebase, y elegir el método más adecuado según el contexto del proyecto.