Domina Git Rebase y el Rebase Interactivo
Guía práctica de git rebase e interactivo: rebase frente a merge, squash de commits, reescribir el historial con seguridad y flujos de equipo limpios.

Git rebase reescribe el historial de commits. Esa frase te entusiasma o te aterra. Ambas reacciones son válidas. Rebase es la herramienta de edición de historial más poderosa de Git y, como toda herramienta poderosa, requiere comprensión antes de usarla.
La gran pregunta que discuten los equipos es: ¿rebase o merge? Merge preserva el historial exacto de cómo las ramas se separaron y se volvieron a unir. Rebase crea un historial lineal y limpio, más fácil de leer y de recorrer con bisect. Ninguno es universalmente mejor — la elección correcta depende del flujo de trabajo de tu equipo y de lo que valoras en el historial de commits.
Rebase vs Merge: La Disyuntiva
# Starting state:
# main: A --- B --- C
# feature: \--- D --- E
# After merge:
# main: A --- B --- C ------- M
# feature: \--- D --- E ---/
# Creates a merge commit (M). Full history preserved.
# After rebase:
# main: A --- B --- C
# feature: --- D' --- E'
# Moves feature commits to tip of main. Linear history.
# D' and E' are NEW commits (different hashes than D and E)// When to use each approach
const guidelines = {
rebase: {
use: [
"Updating feature branch with latest main changes",
"Cleaning up local commits before opening a PR",
"Squashing WIP commits into logical units",
"When you want a linear, readable git log",
],
avoid: [
"On commits that others have already pulled",
"On the main/release branch directly",
"When you need to preserve exact merge history",
],
},
merge: {
use: [
"Merging feature branches into main (via PR)",
"When you need to know when branches diverged",
"When preserving contributor attribution matters",
"On shared branches with multiple contributors",
],
avoid: [
"For keeping feature branches up-to-date (creates noise)",
],
},
};Flujo de Trabajo Básico de Rebase
El uso más común de rebase: actualizar tu rama de feature con los cambios de main antes de abrir un pull request.
# You're working on feature/auth and main has moved ahead
git checkout feature/auth
git fetch origin
# ❌ Merge creates unnecessary merge commits in your branch
git merge origin/main
# "Merge branch 'main' into feature/auth" — adds noise to history
# ✅ Rebase moves your commits to the tip of main
git rebase origin/main
# Your commits are replayed on top of the latest main
# No merge commit, clean linear history
# If conflicts occur during rebase:
# 1. Fix conflicts in the files
# 2. git add <resolved-files>
# 3. git rebase --continue
# Repeat for each conflicting commit
# If rebase goes wrong, abort and return to original state:
git rebase --abort# After rebase, your branch has rewritten commits (new hashes)
# Force-push is required to update the remote branch
git push --force-with-lease origin feature/auth
# --force-with-lease is safer than --force:
# It fails if someone else pushed to the branch since your last fetch
# Prevents accidentally overwriting a teammate's workRebase Interactivo: Reescribiendo el Historial
El rebase interactivo (git rebase -i) te permite editar, combinar (squash), reordenar y eliminar commits. Así es como conviertes commits desordenados de trabajo en progreso en un historial limpio y fácil de revisar.
# Rewrite the last 5 commits
git rebase -i HEAD~5
# This opens your editor with:
pick abc1234 Add user authentication endpoint
pick def5678 WIP: fix typo in auth
pick ghi9012 WIP: forgot to add test
pick jkl3456 Add authorization middleware
pick mno7890 Fix lint errors in auth module
# Commands:
# pick = use commit as-is
# reword = use commit but edit the message
# edit = pause at this commit for amending
# squash = merge into previous commit (keep both messages)
# fixup = merge into previous commit (discard this message)
# drop = remove this commit entirely# Clean up the history:
pick abc1234 Add user authentication endpoint
fixup def5678 WIP: fix typo in auth
fixup ghi9012 WIP: forgot to add test
pick jkl3456 Add authorization middleware
fixup mno7890 Fix lint errors in auth module
# Result: 2 clean commits instead of 5 messy ones:
# abc1234' Add user authentication endpoint
# jkl3456' Add authorization middleware
# The WIP and lint-fix commits are absorbed into their parent commitsPatrones Prácticos de Rebase Interactivo
# Pattern 1: Squash all feature commits into one
git rebase -i main
# Mark all commits except the first as "squash"
# Write a comprehensive commit message for the whole feature
# Pattern 2: Split a commit that does too much
git rebase -i HEAD~3
# Mark the commit as "edit"
# When rebase pauses:
git reset HEAD~1 # Undo the commit but keep changes
git add src/auth.ts # Stage first logical change
git commit -m "Add auth validation logic"
git add src/middleware.ts # Stage second logical change
git commit -m "Add auth middleware"
git rebase --continue
# One commit becomes two focused commits
# Pattern 3: Reorder commits for better review
git rebase -i HEAD~4
# Move the "add tests" commit right after the "add feature" commit
# So the PR reads: feature → tests → refactor → docs
# Pattern 4: Fix a commit message deep in history
git rebase -i HEAD~10
# Mark the target commit as "reword"
# Edit the message when prompted// ❌ Commit history that's hard to review
const badHistory = [
"WIP",
"fix",
"more fixes",
"actually fix the thing",
"oops forgot file",
"lint",
"address PR feedback",
"fix tests",
"final fix",
];
// ✅ Commit history after interactive rebase
const cleanHistory = [
"feat: add user authentication with JWT",
"feat: add role-based authorization middleware",
"test: add auth and authorization test suites",
"docs: update API documentation for auth endpoints",
];
// Each commit is a logical unit that can be reviewed,
// reverted, or cherry-picked independentlyManejo de Conflictos Durante el Rebase
Rebase reproduce los commits uno por uno. Si un commit entra en conflicto con la rama de destino, Git se detiene y te pide que lo resuelvas — para cada commit conflictivo, individualmente.
# During rebase, Git shows:
# CONFLICT (content): Merge conflict in src/auth.ts
# Fix conflicts and run "git rebase --continue"
# Step 1: See which files have conflicts
git status
# Both modified: src/auth.ts
# Step 2: Open the file and resolve conflicts
# <<<<<<< HEAD
# const token = jwt.sign(payload, SECRET, { expiresIn: '1h' });
# =======
# const token = jwt.sign(payload, config.secret, { expiresIn: '24h' });
# >>>>>>> Add authentication with configurable secret
# Step 3: Choose the right version (or combine both)
# const token = jwt.sign(payload, config.secret, { expiresIn: '1h' });
# Step 4: Stage resolved files and continue
git add src/auth.ts
git rebase --continue
# Git moves to the next commit in the rebase# If you mess up a conflict resolution:
git rebase --abort # Return to the exact state before rebase
# Pro tip: enable rerere (Reuse Recorded Resolution)
git config --global rerere.enabled true
# Git remembers how you resolved a conflict and auto-applies
# it if the same conflict appears again (common with long-lived branches)La Regla de Oro del Rebase
Nunca hagas rebase de commits que ya fueron subidos a una rama compartida y descargados por otras personas. Rebase reescribe los hashes de los commits. Si un compañero de equipo tiene commits basados en los hashes antiguos, su historial diverge del tuyo.
# ❌ DANGEROUS: rebasing main after others have pulled
git checkout main
git rebase feature/experiment
git push --force
# Everyone who pulled main now has conflicting history
# They'll see "divergent branches" errors
# ❌ DANGEROUS: rebasing a shared feature branch without coordination
git checkout feature/shared-work
git rebase origin/main
git push --force
# Your teammate's local branch now conflicts with remote
# ✅ SAFE: rebase your own feature branch before PR
git checkout feature/my-work # Only you work on this branch
git rebase origin/main
git push --force-with-lease origin feature/my-work
# ✅ SAFE: interactive rebase on unpushed commits
git rebase -i HEAD~3 # Only local commits, never pushed
# Free to squash, reorder, reword — nobody has these commitsPuntos Clave
- Usa rebase para actualizar ramas de feature y merge para integrar a main — rebase mantiene tu rama lineal y limpia; merge preserva el punto de integración en las ramas compartidas
- El rebase interactivo convierte commits desordenados de WIP en commits revisables — combina (squash) los commits de fixup, reescribe los mensajes y reordena los commits antes de abrir un PR
- Nunca hagas rebase de commits compartidos — solo aplica rebase a los commits que existen únicamente en tu rama; hacer rebase del historial compartido rompe el estado local de todos los demás
- Usa
--force-with-leaseen lugar de--force— evita sobrescribir el push de otra persona que haya ocurrido entre tu fetch y tu push - Activa
rererepara la resolución repetida de conflictos — si haces rebase con frecuencia y te encuentras con los mismos conflictos,rerereregistra y aplica automáticamente tus resoluciones


