Hacer squash en Git es unir varios commits en uno solo. Se usa sobre todo antes de un pull request: en vez de diez commits como “arreglo”, “ahora sí” y “typo”, tu rama queda con un único commit que describe el cambio completo. El historial se lee mejor y es más fácil revertir una funcionalidad entera si hace falta.
En esta nota te explico tres formas de hacerlo, cuándo usar cada una y cómo deshacerlo si algo sale mal.
Antes de empezar #
Supongamos que estás en una rama feature que salió de main y tiene varios commits:
git log --oneline a1b2c3d fix: typo
d4e5f6a feat: validación del formulario
9f8e7d6 feat: formulario de contacto
b6adbbc (origin/main, main) chore: versión inicial Quieres que los tres commits de arriba queden en uno solo, encima de main.
Forma 1: git rebase -i (la más común) #
El rebase interactivo te deja elegir qué commits unir.
1. Abre el rebase desde el punto donde tu rama salió de main:
git rebase -i main Si solo quieres unir los últimos commits, también puedes indicar cuántos:
git rebase -i HEAD~3 2. Marca los commits a unir. Git abre tu editor con una lista, del más viejo al más nuevo:
pick 9f8e7d6 feat: formulario de contacto
pick d4e5f6a feat: validación del formulario
pick a1b2c3d fix: typo Deja el primero en pick y cambia los demás a squash (o solo s):
pick 9f8e7d6 feat: formulario de contacto
squash d4e5f6a feat: validación del formulario
squash a1b2c3d fix: typo Si en vez de squash usas fixup (o f), Git une el commit pero descarta su mensaje. Es útil para commits tipo “typo”.
3. Guarda y cierra el editor. Git te pide el mensaje final del commit unido. Escríbelo, guarda y cierra.
Si se abrió Vim: pulsa
ipara escribir,Escpara salir del modo de edición y luego escribe:wqyEnterpara guardar y cerrar. Si prefieres VS Code como editor de Git:git config --global core.editor "code --wait".
Listo. Comprueba con git log --oneline que ahora tienes un solo commit encima de main.
Forma 2: git reset —soft (la más rápida) #
Si quieres unir todos los commits de tu rama en uno, sin editar listas:
git reset --soft main
git commit -m "feat: formulario de contacto con validación" git reset --soft mueve la rama al commit de main pero deja todos tus cambios preparados (en el stage). Después haces un solo commit con todo.
Usa
--soft, nunca--hard.git reset --hardborra tus cambios.
Si tu rama main local está desactualizada, usa el punto exacto donde se separó tu rama:
git reset --soft $(git merge-base HEAD origin/main) Forma 3: git merge —squash (al integrar en main) #
Si no quieres tocar tu rama y prefieres unir los commits en el momento de integrarla:
git switch main
git merge --squash feature
git commit -m "feat: formulario de contacto con validación" Todos los cambios de feature entran en main como un solo commit. Tu rama feature queda igual.
En GitHub esto mismo es el botón “Squash and merge” del pull request. Si tu equipo lo usa, no necesitas hacer squash a mano.
Cómo subir el squash a GitHub #
Las formas 1 y 2 reescriben el historial de tu rama, así que un git push normal será rechazado. Usa:
git push --force-with-lease --force-with-lease es más seguro que --force: si alguien subió algo a tu rama que tú no tienes, el push falla en vez de borrarlo.
Nunca hagas squash de commits que ya están en una rama compartida como
main. Reescribirías el historial de todo el equipo.
Cómo deshacer un squash #
Git guarda dónde estaba tu rama antes del cambio. Búscalo en el reflog:
git reflog 3c4d5e6 HEAD@{0}: rebase (finish): returning to refs/heads/feature
...
a1b2c3d HEAD@{4}: commit: fix: typo Y vuelve a ese punto:
git reset --hard HEAD@{4} Aquí --hard sí es lo que quieres: estás volviendo exactamente al estado anterior.
¿Cuál uso? #
| Situación | Forma |
|---|---|
| Quiero elegir qué commits unir | git rebase -i |
| Quiero unir toda mi rama en un commit | git reset --soft |
| Quiero unir al integrar, sin tocar mi rama | git merge --squash o “Squash and merge” en GitHub |
Un último consejo: si vas a escribir un buen mensaje para el commit unido, usa Conventional Commits. Te explico cómo forzarlo en tu proyecto en esta nota sobre husky y commitlint.