Git merge vs rebase: cuál elegir para tu equipo
Tanto merge como rebase integran los cambios de dos ramas, pero tratan el historial de forma distinta: merge lo conserva tal cual y añade un commit de fusión, y rebase reescribe tus commits sobre la nueva base y deja un historial lineal. Regla práctica: rebase para ordenar tus commits aún no publicados, merge para integrar el trabajo terminado en las ramas compartidas.
En resumen: diferencia entre merge y rebase
El debate «git merge vs rebase» no va realmente de qué comando es mejor, sino de qué historial del proyecto quieres ver. Ambos comandos llevan al mismo código final. Lo que cambia es el camino que queda registrado en el log.
- Merge une dos líneas del historial y deja constancia honesta de que el trabajo avanzó en paralelo. Los commits existentes no cambian y se añade un merge commit con dos padres.
- Rebase reescribe tus commits como si hubieras empezado a trabajar desde la versión más reciente de la rama base. El historial queda como una línea recta, pero los commits reciben hashes nuevos.
La mecánica de cada comando (opciones, resolución de conflictos, modo interactivo) la explicamos en artículos aparte. Aquí nos centramos solo en elegir la estrategia.
Cómo queda el historial en cada caso
Situación de partida: creaste feature, hiciste dos commits y, mientras tanto, en main aparecieron dos commits de otras personas.
D---E feature
/
A---B---C---F---G main
Después de git merge feature en main:
D---E
/ \
A---B---C---F---G---M main
Después de git rebase main en feature y del fast-forward de main:
A---B---C---F---G---D'---E' main
En el primer caso el historial muestra que la funcionalidad se desarrolló en paralelo y cuándo se integró. En el segundo, el historial se lee como un relato secuencial, pero el hecho del trabajo en paralelo desaparece: D' y E' son commits nuevos creados en el momento del rebase.
Tabla comparativa: git merge vs rebase
| Criterio | git merge | git rebase |
|---|---|---|
| Commits existentes | No cambian | Se recrean con hashes nuevos |
| Forma del historial | Grafo ramificado con merge commits | Lineal |
| Seguridad en ramas compartidas | Siempre seguro | Peligroso con commits publicados |
| ¿Hace falta force push? | No | Sí, si la rama ya está en el servidor |
| Conflictos | Se resuelven una vez, en el merge commit | Pueden aparecer en cada commit que se traslada |
| Contexto de «de dónde viene» | Se conserva | Se pierde |
| Revertir una funcionalidad completa | Un solo git revert -m 1 del merge commit | Revert de cada commit o de un rango |
Comodidad con git bisect y git log | Grafo más difícil de leer | Más sencillo: una sola línea recta |
| Curva de aprendizaje | Baja | Más alta, hay que entender la reescritura del historial |
| Limpieza de commits (squash, reword) | Solo --squash de todo a la vez | Flexible con rebase -i |
Ventajas y desventajas de merge
Ventajas
- No destruye el historial. Todo lo publicado sigue en su sitio. Tus compañeros no tendrán que arreglar nada después de lo que hagas.
- El conflicto se resuelve una sola vez. Aunque la rama tenga 30 commits, trabajas con el estado final, no con cada paso.
- Se conserva el contexto. Por el merge commit se ve qué tarea entró en la rama principal y cuándo, y es fácil revertirla entera.
Desventajas
- Grafo ruidoso. Con sincronizaciones frecuentes, el historial se llena de commits «Merge branch 'main' into feature» y
git log --graphacaba pareciendo un mapa de vías de tren. - Los commits de borrador acaban en el historial. «wip», «fix», «otro fix» se quedan para siempre en la rama principal si no se combinan.
Ventajas y desventajas de rebase
Ventajas
- Historial lineal y legible. Cada commit está en su sitio,
git logse lee como una lista de cambios ygit bisectencuentra más fácilmente el commit que introdujo el error. - Posibilidad de ordenar los commits antes de la revisión: combinarlos, renombrarlos, reordenarlos.
- Sin merge commits técnicos por sincronizarse con la rama principal.
Desventajas
- Reescribe el historial. Hacer rebase de una rama compartida ya publicada rompe el trabajo de todos los que la descargaron.
- Exige force push en las ramas que están en el servidor, y por tanto disciplina y
--force-with-lease. - Conflictos repetidos. El mismo fragmento puede entrar en conflicto en varios commits seguidos.
- Puede que los commits intermedios no compilen. Tras trasladarlos a la nueva base, nadie ha probado esos commits antiguos en el nuevo entorno.
Cuándo usar cada uno
Rebase para tu trabajo local
Actualizas tu rama antes de subirla: git pull --rebase. Preparas la rama para revisión y quieres quitar los commits de borrador: git rebase -i. Tu rama de feature personal se ha quedado atrás respecto a main: git rebase origin/main. En todos estos casos se reescriben commits que solo has visto tú (o que solo te pertenecen a ti).
Merge para ramas compartidas e integración
Una funcionalidad terminada se integra en main o develop. Varias personas trabajan en la misma rama. Hay que fusionar una rama de release de vuelta en la principal. Aquí lo importante es no tocar los commits ya publicados, y merge es la única opción correcta.
Una regla sencilla para decidir
Si los commits solo los tienes tú, puedes hacer rebase. Si alguien ya los ha descargado, solo merge.
Flujos de trabajo habituales para un equipo
| Flujo | Cómo funciona | Para quién |
|---|---|---|
| Solo merge | Las funcionalidades se integran con --no-ff y la sincronización se hace con git merge main | Equipos que empiezan con Git, o donde importan la cronología completa y los reverts sencillos |
| Rebase + merge | Antes de integrar, la rama se rebasa sobre main y luego se crea un merge commit con --no-ff | Equipos que quieren un historial limpio y también los límites de cada funcionalidad |
| Rebase + fast-forward | La rama se rebasa y se integra por fast-forward; el historial es completamente lineal | Equipos pequeños con commits atómicos y cuidados |
| Squash merge | Cada pull request se convierte en un único commit en main | Equipos con tareas cortas en los que no hace falta el historial detallado de la rama |
En GitHub y GitLab estos flujos corresponden a los botones «Create a merge commit», «Rebase and merge» y «Squash and merge». Lo mejor es permitir en la configuración del repositorio solo la opción elegida, para que el historial no se convierta en una mezcla de estilos.
Configuración que fija la elección
# pull sin merge commits innecesarios
git config --global pull.rebase true
# o bien: pull solo por fast-forward; si no, error y decides tú
git config --global pull.ff only
# siempre un merge commit al integrar funcionalidades
git config --global merge.ff false
Cuidado con merge.ff false: también afecta a git pull en modo merge. Muchos prefieren no activarlo de forma global y escribir --no-ff explícitamente al integrar una funcionalidad.
Ejemplo: la misma tarea en los dos estilos
Veamos un caso real. Llevas tres días desarrollando la funcionalidad de pagos en la rama feature/payment y, mientras tanto, en main se han integrado cinco tareas de otros. Antes del pull request tienes que traer el main actualizado y comprobar que todo funciona.
Opción con merge
git switch feature/payment
git fetch origin
git merge origin/main
# conflictos resueltos una sola vez, git add, git commit
git push
La rama recibe el commit «Merge remote-tracking branch 'origin/main' into feature/payment». El push es normal y los compañeros que siguen la rama no notan nada. Si te sincronizas así cada día, la rama tendrá tres commits de este tipo, y llegarán a main junto con la funcionalidad si se integra sin squash.
Opción con rebase
git switch feature/payment
git fetch origin
git rebase origin/main
# los conflictos se resuelven sobre la marcha, en cada commit: git add, git rebase --continue
git rebase -i origin/main # opcional: combinar los commits de borrador
git push --force-with-lease
La rama parece haberse creado esta mañana a partir del main actualizado, no hay commits sobrantes y al revisor le resulta más fácil leer los cambios paso a paso. El precio es un push forzado y tener que asegurarse de que nadie más hace commits en esa rama.
Qué acabará viendo main
Al integrar mediante pull request, la diferencia se mantiene. El estilo merge dará un grafo con bifurcaciones y fusiones de sincronización; el estilo rebase, una cadena ordenada de commits de la funcionalidad que se puede integrar por fast-forward o con un único merge commit. El código será el mismo siempre que los conflictos se resuelvan igual.
Cómo decidir en equipo
Responde a unas cuantas preguntas. ¿Trabajan varias personas en la misma rama? Si es así, rebase queda descartado para esa rama. ¿Qué experiencia tiene el equipo con Git? Si entra gente nueva a menudo, empieza con merge y squash merge, que perdonan los errores. ¿Necesitáis la cronología completa para auditorías y análisis de incidentes? Entonces los merge commits de cada funcionalidad son útiles. ¿Os importa un git log legible y usáis git bisect con frecuencia? Entonces la balanza se inclina por rebase y un historial lineal.
Deja la decisión por escrito en el CONTRIBUTING o el README del repositorio y activa la protección de la rama principal: prohibir el force push, exigir pull request y fijar el método de fusión permitido. Una regla respaldada por la configuración funciona mejor que cualquier acuerdo verbal.
Mitos frecuentes
- «Rebase es para expertos y merge para principiantes». No: son herramientas distintas para tareas distintas. Los desarrolladores con experiencia usan ambas.
- «Los merge commits son basura». Los de sincronización, sí, a menudo son ruido. Pero el merge commit que integra una funcionalidad es un punto útil: ahí se ve toda la tarea y se puede revertir de una vez.
- «Con rebase hay menos conflictos». Los conflictos son los mismos, porque cambian las mismas líneas. Rebase solo los reparte por commits, mientras que merge los resuelve de golpe.
- «Rebase pierde commits». Los commits antiguos siguen en
git reflogy se pueden recuperar mientras el recolector de basura no los elimine.
Conclusión
Elegir entre git merge vs rebase es elegir entre una cronología fiel y un historial lineal y legible. Merge es seguro y conserva el contexto; rebase aporta limpieza, pero reescribe los commits. La práctica más fiable es combinarlos: rebasar y limpiar tu rama mientras sea solo tuya, e integrar el trabajo terminado en las ramas compartidas con merge o squash según las reglas del equipo. Lo esencial es acordar un flujo y fijarlo en la configuración del repositorio. Ambas estrategias y el trabajo con ramas en equipo se practican en el curso de Git.
Preguntas frecuentes
¿Qué conviene usar con git pull, merge o rebase?
Para actualizar una rama local es más cómodo rebase: tus commits no publicados se colocan encima de los remotos recientes sin un merge commit extra. Se activa con git config --global pull.rebase true.
¿Se pueden combinar merge y rebase en el mismo proyecto?
Sí, y es el enfoque más habitual: rebase para tus ramas y merge para las compartidas. Lo importante es que todo el equipo conozca la regla.
¿Qué debería usar alguien que empieza?
Empieza con merge: no reescribe el historial y es más difícil romper algo. Aprende rebase en tus ramas locales cuando ya domines reflog y el force push.
¿La estrategia elegida afecta al código final?
No; si los conflictos se resuelven igual, el estado final de los archivos es idéntico. Solo cambia el historial de commits que queda registrado.
¿En qué se diferencia squash merge de rebase?
Squash merge comprime toda la rama en un único commit nuevo en la rama principal, mientras que rebase traslada cada commit por separado. Ambos dan un historial lineal, pero squash pierde el detalle paso a paso.
Este tema se explica a fondo y con práctica en el curso «Git desde cero hasta desarrollador seguro».
- Flujos de trabajo con Git en equipos reales: ¿qué workflow elegir?
- Herramientas avanzadas: rebase, stash, cherry-pick y etiquetas