Cuando trabajamos con Git y utilizamos plataformas como GitHub, GitLab o Bitbucket para gestionar nuestros repositorios, nos encontramos con varias formas de fusionar ramas que pueden afectar significativamente al historial del proyecto. Estas opciones son el merge commit, el rebase and merge y el squash and merge, y cada una tiene sus particularidades que conviene entender para mantener un historial limpio y manejable.
La opción más tradicional y común es el merge commit. Cuando hacemos un merge de esta forma, Git crea un commit especial que une las dos ramas, dejando un nudo en el historial. Esto significa que si visualizamos el grafo de commits con git log --graph --oneline, veremos cómo las ramas se bifurcan y luego se unen en un punto, formando esos nudos característicos. Aunque funcional, este método puede hacer que el historial se vea más desordenado y menos lineal, algo que a algunos desarrolladores les puede resultar poco estético o difícil de seguir.
Por otro lado, tenemos la opción de rebase and merge. Esta estrategia consiste en reescribir el historial de la rama que queremos fusionar para que sus commits se apliquen encima de la rama principal, como si hubieran sido creados directamente a partir de ella. Esto se traduce en un historial más lineal y limpio, sin esos nudos que aparecen con los merge commits. El rebase es una operación destructiva en el sentido de que modifica el historial, pero es muy útil para mantener un registro claro y ordenado de los cambios. Si queremos profundizar en cómo funciona el rebase, podemos recordar que se trata de mover la base de una rama para que parezca que todos los commits se hicieron después del último commit de la rama principal.
Finalmente, la opción que está ganando mucha popularidad es el squash and merge. Esta técnica aplasta todos los commits de una rama en un único commit antes de fusionarlo con la rama principal. Esto es especialmente útil cuando en una rama de desarrollo se han hecho muchos commits intermedios, como correcciones de errores o pequeños ajustes, que no aportan valor individualmente al historial principal. Al hacer squash, el historial queda mucho más limpio y fácil de entender, ya que cada funcionalidad o cambio importante queda representado por un solo commit. Esto también facilita el uso de herramientas como git blame, que nos permiten identificar rápidamente quién hizo un cambio y por qué, sin tener que navegar por un historial lleno de commits menores o de merge.
Para ilustrar cómo se vería un squash, imaginemos que tenemos dos commits en una rama de desarrollo. Al hacer squash and merge, esos dos commits se combinan en uno solo que contiene todas las modificaciones de ambos. El resultado es un historial más compacto y legible.
# Visualización del historial con merge commit (nudos visibles)
git log --graph --oneline
# Rebase para aplicar commits encima de la rama principal
git rebase main
# Squash para combinar múltiples commits en uno solo
git merge --squash feature-branch
git commit -m "Funcionalidad implementada en un único commit"
En resumen, elegir entre merge commit, rebase and merge o squash and merge depende de nuestras preferencias y necesidades en cuanto a la limpieza y claridad del historial. El merge commit es sencillo y mantiene el historial completo con todos los detalles, el rebase and merge ofrece un historial lineal y ordenado, y el squash and merge nos permite presentar los cambios de forma compacta y clara, ideal para mantener un repositorio limpio y fácil de entender.