Bienvenido a nuestra guía definitiva de los comandos git merge y git rebase. Este tutorial te enseñará todo lo que necesitas saber sobre la combinación de múltiples ramas con Git.

Git Merge

El comando git merge fusionará cualquier cambio que se haya hecho en la base de código en una rama separada de tu rama actual como un nuevo commit.

La sintaxis del comando es la siguiente:

git merge NOMBRE-DE-LA-RAMA

Por ejemplo, si estás trabajando actualmente en una rama llamada dev y deseas fusionar los nuevos cambios que se hayan realizado en una rama llamada new-features, ejecutarías el siguiente comando:

git merge new-features

Nota: Si hay algún cambio al que no se le ha hecho commit en la rama actual, Git no te permitirá fusionar hasta que se hayan realizado commit todos los cambios en tu rama actual. Para manejar esos cambios, puedes hacer lo siguiente:

Crear una nueva rama y realizar commit a los cambios

git checkout -b nombre-de-la-nueva-rama
git add .
git commit -m "<tu mensaje de commit>"

Guardarlos en el stash

git stash               # agregarlos al stash
git merge new-features  # fusionarlos
git stash pop           # obtén los cambios devuelta al árbol de trabajo (working tree)

Abandonar todos los cambios

git reset --hard        # remueve todos los cambios pendientes

Git Rebase

Realizar un rebase a una rama (branch) en Git es una form ade mover la totalidad de una rama a otro punto del árbol. El ejemplo más simple es mover una rama más arriba en el árbol. Digamos que tenemos una rama que se separó de la rama master en el punto A:

        /o-----o---o--o-----o--------- branch
--o-o--A--o---o---o---o----o--o-o-o--- master

Cuando se realiza rebase se puede mover así:

                                   /o-----o---o--o-----o------ branch
--o-o--A--o---o---o---o----o--o-o-o master

Para realizar rebase, asegúrate de tener todos los commits que quieras en el rebase en tu rama master. Revisar la rama en la que quieres hacer el rebase y escribe git rebase master (donde master es la rama en la que quieres hacer el rebase).

También es posible hacer rebase en una rama diferente, de modo que, por ejemplo, una rama que se basaba en otra rama (llamémosla feature) se rebasa en master:

                            /---o-o branch
           /---o-o-o-o---o--o------ feature
----o--o-o-A----o---o--o-o-o--o--o- master

Después de git rebase master branch o git rebase master si te encuentras (checked out) en branch, obtendrás:

           /---o-o-o-o---o--o------ feature
----o--o-o-A----o---o--o-o-o--o--o- master
                                  \---o-o branch

Git rebase interactivo en la consola

Para usar git rebase en la consola con una lista de commits, puedes elegir, editar o soltar en el rebase:

  • Introduce git rebase -i HEAD~5 con el último número que sea cualquier número de commits del más reciente hacia atrás que quieras revisar.
  • En vim, presiona esc, luego i para empezar a editar la prueba.
  • A la izquierda puedes sobreescribir pick con uno de los comandos de abajo. Si quieres aplastar (squash) un commit a uno anterior y descartar el mensaje de commit, introduce f en lugar de pick en el commit.
  • Guarda y sal del editor de texto.
  • Cuando se detiene a rebase, haz los ajustes necesarios, y luego usa git rebase --continue hasta que el rebase sea exitoso.
  • Si el rebase es exitoso, entonces necesitas forzar el push de tus cambios con git push -f para agregar la versión con rebase a tu repositorio remoto.
  • Si hay un "merge conflict" (conflicto al querer fusionar las ramas), hay varias maneras de arreglarlo, incluyendo seguir las sugerencias de esta guía. Una forma es abrir los archivos en un editor de texto y eliminar las partes del código que no quieras. Luego usa git add <file name> seguido de git rebase --continue. Puedes saltarte el commit de conflicto ejecutando git rebase --skip, para el rebase ejecutando git rebase --abort en tu consola.
pick 452b159 <message for this commit>
pick 7fd4192 <message for this commit>
pick c1af3e5 <message for this commit>
pick 5f5e8d3 <message for this commit>
pick 5186a9f <message for this commit>

# Rebase 0617e63..5186a9f onto 0617e63 (30 commands)
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but stop to edit the commit message.
# e, edit = use commit, but stop to amend or add commit.
# s, squash = use commit, meld into previous commit and stop to edit the commit message.
# f, fixup = like "squash", but discard this commit's log message thus doesn't stop.
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit
#
# These lines can be re-ordered; they are executed from top to bottom. 
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

Merge Conflicts

Un merge conflict es cuando realizar commits en ramas separadas que alteran la misma línea de manera conflictiva. Si esto ocurre, Git no sabrá que versión del archivo guardar en un mensaje de error similar al siguiente:

CONFLICT (content): Merge conflict in resumé.txt Automatic merge failed; fix conflicts and then commit the result.

Si miras el archivo resumé.txt en tu editor de texto, puedes ver dónde tuvo lugar el conflicto:

<<<<<<< HEAD
Address: 808 South Street
=======
Address: 505 North Street
>>>>>>> updated_address

Git agregó algunas líneas adicionales en el archivo:

  • <<<<<<< HEAD
  • =======
  • >>>>>>> updated_address

Piensa en  ======= como la línea divisoria del conflicto. Todo lo que hay entre <<<<<<< HEAD y ======= es el contenido de la rama actual a la que apunta HEAD ref. Por otro lado, todo lo que hay entre  ======= y >>>>>>> updated_address es el contenido de la rama que se está fusionando, updated_address.

Git Merge vs Git Rebase

Tanto git merge como git rebase son comandos muy útiles, y uno no es mejor que el otro. Sin embargo, hay algunas diferencias muy importantes entre los dos comandos que tú y tu equipo deben tener en cuenta.

Cada vez que se ejecuta git merge, se crea un merge commit extra. Siempre que trabajes en tu repositorio local, tener demasiados merge commits puede hacer que el historia del commits parezca confuso. Una forma de evitar el merge commit es usar git rebase en su lugar.

git rebase es una característica muy poderosa. Dicho esto, también es arriesgado si no se usa de la manera correcta. git rebase altera el historial de commits, así que úsalo con cuidado. Si el rebase se hace en el repositorio remoto, entonces puede crear muchos problemas cuando otros desarrolladores intentan sacar los últimos cambios de código del repositorio remoto. Recuerda que sólo debes ejecutar git rebase en un repositorio local.

Eso es todo lo que necesitas saber para merge y rebase con lo mejor de ellos.

Traducido del artículo - The Ultimate Guide to Git Merge and Git Rebase