El debate rebase vs merge es una de las discusiones más comunes en flujos de trabajo Git. Ambos comandos integran cambios de una rama a otra, pero de formas fundamentalmente diferentes.
Cómo funciona Git Merge
Git merge crea un nuevo "commit de merge" que une los historiales de ambas ramas.
Git encuentra el ancestro común y crea un nuevo commit combinando los cambios.
A---B---C feature
/ \
D---E---F---G---H main (merge commit)
$ git checkout main
$ git merge featureCómo funciona Git Rebase
Git rebase mueve tus commits encima de otra rama, creando una secuencia lineal.
Git remueve temporalmente tus commits, actualiza la rama y reaplicar cada commit uno por uno.
Before rebase:
A---B---C feature
/
D---E---F---G main
After rebase:
A'--B'--C' feature
/
D---E---F---G main
$ git checkout feature
$ git rebase mainComparación visual
╔═══════════════════════════════════════════╗
║ MERGE RESULT ║
║ ║
║ D---E---F---G---H main ║
║ \ / ║
║ A---B---C feature ║
║ ║
║ ✓ Preserves all commits ║
║ ✓ Shows merge point ║
║ ✗ Non-linear history ║
╚═══════════════════════════════════════════╝
╔═══════════════════════════════════════════╗
║ REBASE RESULT ║
║ ║
║ D---E---F---G---A'--B'--C' main ║
║ ║
║ ✓ Clean linear history ║
║ ✓ Easy to read ║
║ ✗ Rewrites commit hashes ║
╚═══════════════════════════════════════════╝Cuándo usar Merge
- Ramas públicas/compartidas — Merge nunca reescribe el historial.
- Preservar contexto — El commit de merge muestra cuándo se integró una rama.
- Colaboración en equipo — Cuando varias personas trabajan en la misma rama.
- Ramas de release — Preserva el punto de integración exacto.
# Merge with merge commit (recommended for main)
$ git checkout main
$ git merge --no-ff feature
$ git push origin mainCuándo usar Rebase
- Ramas feature (antes de merge a main) — Historial lineal limpio.
- Mantenerse actualizado — Rebase tu rama feature sobre main sin commits de merge.
- Antes de enviar PR — Commits limpios son más fáciles de revisar.
- Limpiar commits locales — Rebase interactivo para squash, reordenar, editar.
# Update feature branch with latest main
$ git checkout feature
$ git rebase main
# If conflicts occur, resolve them, then:
$ git add .
$ git rebase --continueRebase interactivo: squash, fixup, reordenar
El rebase interactivo (git rebase -i) es una de las funciones más poderosas de Git.
$ git rebase -i HEAD~4
# Editor opens:
pick a1b2c3d Add user authentication
pick e4f5g6h Fix typo in auth
pick i7j8k9l Add password validation
pick m0n1o2p Fix lint error
# Change to:
pick a1b2c3d Add user authentication
fixup e4f5g6h Fix typo in auth # merge into previous, discard message
pick i7j8k9l Add password validation
fixup m0n1o2p Fix lint error # merge into previous, discard message
# Result: 2 clean commits instead of 4
# Commands:
# pick = use commit as-is
# squash = merge into previous commit, keep message
# fixup = merge into previous commit, discard message
# reword = use commit but edit message
# drop = remove commit entirelyRegla de oro: Nunca Rebase ramas públicas
Si una rama ha sido pusheada y otros trabajan en ella, NO la rebases.
Regla de oro: Solo rebasa commits que NO han sido pusheados a un remoto compartido.
# ❌ DANGEROUS: Rebasing a shared branch
$ git checkout main
$ git rebase feature # NEVER do this!
# ✅ SAFE: Rebasing your own feature branch
$ git checkout my-feature # only I work on this
$ git rebase main # safe!
$ git push --force-with-lease origin my-featureMerge vs Rebase: Comparación completa
| Criterio | Merge | Rebase |
|---|---|---|
| History | Non-linear, preserves branches | Linear, clean |
| Commit hashes | Preserved | Changed (new hashes) |
| Conflict resolution | Once (in merge commit) | Per commit (may resolve multiple times) |
| Traceability | High (merge commit shows context) | Medium (linear but no branch info) |
| Safety | Safe (no history rewrite) | Risky (rewrites history) |
| For shared branches | ✅ | ❌ |
| For personal branches | ✅ | ✅ |
| Reversibility | Easy (git revert) | Harder (requires reflog) |
| git bisect | Harder (non-linear) | Easier (linear history) |
Flujos de trabajo Git comunes
Feature Branch Workflow
Crear rama feature → desarrollar → rebase a main → merge con --no-ff.
$ git checkout -b feature/login
# ... develop ...
$ git rebase main # clean up history
$ git checkout main
$ git merge --no-ff feature/login # merge with commit
$ git branch -d feature/loginGitflow Workflow
Usa develop, feature, release, hotfix. Siempre merge entre ramas de larga duración.
# Always merge between long-lived branches
$ git checkout develop
$ git merge --no-ff feature/login
$ git checkout release/1.0
$ git merge --no-ff develop
$ git checkout main
$ git merge --no-ff release/1.0
$ git tag v1.0Trunk-Based Development
Ramas feature cortas (< 1 día). Rebase frecuente, merge rápido.
# Short-lived branch, rebase often
$ git checkout -b fix/typo
# ... quick fix ...
$ git rebase main
$ git checkout main
$ git merge fix/typo # fast-forward
$ git pushEscenarios peligrosos
| Escenario | Riesgo | Prevención |
|---|---|---|
| Rebase main/master | Everyone's history breaks | Never rebase main |
| Rebase shared feature branch | Collaborators face divergent history | Use merge for shared branches |
| git push --force | Overwrites remote changes | Use --force-with-lease instead |
| Wrong conflict resolution during rebase | Code loss or corruption | Review each conflict, use git rebase --abort to restart |
| Rebase branch with merge commits | Merge commits flattened, confusing | Use --rebase-merges or avoid |
Preguntas frecuentes
¿Se puede deshacer un rebase?
Sí. Usa git reflog para encontrar el hash anterior y git reset --hard para restaurar.
¿Rebase o merge para actualizar mi rama feature?
Solo tú en la rama: rebase. Rama compartida: merge.
¿Qué es git pull --rebase?
Reproduce tus commits locales sobre los cambios remotos, sin commit de merge.
¿Qué pasa si rebaso una rama ya pusheada?
Necesitarás force push. Otros tendrán un historial divergente.
¿Squash merge = rebase + squash?
Resultado similar, mecanismo diferente. Rebase -i ofrece más control.
¿Cuál para contribuciones open source?
La mayoría de proyectos open source prefieren commits rebasados y limpios.