← Todos los artículos EN

Cómo hacer merge de una rama de feature con un squash commit

Mantén el historial de tu rama principal limpio aplastando los commits de una feature branch en uno solo antes del merge — paso a paso con un script reutilizable.

Después de una semana de trabajo en una feature branch, tu historial de commits se ve más o menos así:

fix typo
WIP
fix test
WIP again
fix linter
listo ahora sí

Estos commits son útiles mientras trabajas — pero son ruido en el historial de la rama principal. Un squash merge colapsa todos en un único commit descriptivo antes de que lleguen a main.

Qué hace realmente un squash merge

Un squash merge toma todos los cambios de una feature branch y los prepara como un único commit en la rama destino. El historial de commits de la rama original se descarta — solo sobrevive el diff.

El resultado: main se mantiene legible, y cada entrada en git log representa una unidad de trabajo completa y deployable.

main
├── feat: agregar autenticación de usuario (#42)
├── feat: rediseño del flujo de pago (#38)
└── chore: actualizar dependencias (#35)

En vez de:

main
├── fix test
├── WIP
├── fix typo
├── WIP
├── implementación inicial de auth
└── ...

El enfoque manual

Git soporta squash merging de forma nativa:

# Asegúrate de que main esté actualizado
git checkout main
git pull origin main

# Merge con squash — prepara todos los cambios, no hace commit
git merge --squash feature/mi-rama

# Escribe un único mensaje de commit descriptivo
git commit -m "feat: implementar autenticación de usuario"

# Limpia la feature branch
git branch -d feature/mi-rama
git push origin --delete feature/mi-rama

El flag --squash es la clave: prepara todo sin crear un commit de merge, dándote control total sobre el mensaje final.

Automatizando con un script

Hacer esto repetidamente en docenas de feature branches se vuelve tedioso. Un script reutilizable se encarga de la mecánica:

#!/bin/bash
# git_squash.sh — hace merge de una feature branch con un squash commit

set -e

FEATURE_BRANCH=$1
TARGET_BRANCH=$2

if [ -z "$FEATURE_BRANCH" ] || [ -z "$TARGET_BRANCH" ]; then
  echo "Uso: git-squash <feature-branch> <target-branch>"
  exit 1
fi

echo "→ Squash merging $FEATURE_BRANCH en $TARGET_BRANCH"

# Backup de la feature branch
git branch "${FEATURE_BRANCH}_backup"

# Cambiar al target y actualizar
git checkout "$TARGET_BRANCH"
git pull origin "$TARGET_BRANCH"

# Squash merge
git merge --squash "$FEATURE_BRANCH"

# Commit (abre el editor para el mensaje)
git commit

# Push al remoto
git push origin "$TARGET_BRANCH"

# Limpieza
git branch -d "$FEATURE_BRANCH"
git branch -d "${FEATURE_BRANCH}_backup"

echo "✓ Listo. $FEATURE_BRANCH mergeado en $TARGET_BRANCH."

Configurar el alias

Guarda el script en algún lugar permanente y hazlo ejecutable:

chmod +x ~/scripts/git_squash.sh

Agrega un alias a tu perfil de shell (.zshrc, .bashrc, o .profile):

alias git-squash="~/scripts/git_squash.sh"

Recarga el perfil:

source ~/.zshrc

Ahora puedes hacer squash-merge de cualquier rama con:

git-squash feature-123 main

Cuándo usar squash merges

El squash merge es el default correcto cuando:

  • La feature branch tiene muchos commits pequeños o de fixup que no aportan valor histórico
  • El equipo acordó una estrategia de historial lineal
  • Estás aplicando conventional commits en main y quieres control total sobre el mensaje

No es la opción correcta cuando:

  • Quieres preservar el historial individual de commits para debugging (git bisect se beneficia de commits granulares)
  • Varias personas colaboraron en la rama y la atribución importa
  • Los commits ya son limpios y descriptivos

La alternativa: rebase interactivo

Si quieres aplastar selectivamente algunos commits pero mantener otros, git rebase -i es más quirúrgico:

git rebase -i main

Esto abre un editor donde marcas los commits como pick, squash, o fixup. Más control, un poco más de fricción.

Conclusiones

  • git merge --squash colapsa todos los commits de la rama en un único diff preparado — tú escribes el mensaje final
  • Un historial limpio en main facilita significativamente git log, las code reviews y el debugging de incidentes
  • El script agrega una rama --backup como red de seguridad antes de operaciones destructivas
  • El squash merge es una convención de equipo — acuérdala de antemano y aplícala mediante reglas de branch protection en GitHub/GitLab