git merge y git rebase hacen el mismo trabajo: traer los cambios de un branch hacia otro. Lo que cambia es el historial que dejan, y ese historial decide qué comando te sirve.
Qué hace cada comando
Merge escribe un commit con dos padres. Ese commit registra el momento en que dos caminos se cruzaron, y cada commit de la feature sobrevive como fue escrito.
git checkout feature
git merge main
* merge branch 'main' into feature
|\
| * add user validation
| * create user model
|/
* main commit
Rebase repasa tus commits por encima del destino. Descarta los originales y escribe copias con el mismo contenido y padres nuevos. Los hashes cambian, así que cada referencia vieja a esos commits (un branch, un tag, un link en el PR) queda apuntando a un objeto que nadie tiene.
git checkout feature
git rebase main
* add user validation
* create user model
* main commit
Cuándo conviene merge
- El branch tiene varios autores y el historial de quién aportó qué tiene que quedar registrado.
- El branch vive semanas, como un release branch, y quieres preservar el orden real de los hechos.
- El equipo sigue Git Flow y el commit de merge se vuelve el punto de encuentro entre release y main.
En el pull request, el commit de merge lleva metadatos: quién aprobó, el número del PR, la fecha. La página Configuring pull request merges de GitHub lista los tres formatos aceptados y lo que cada uno escribe en el historial.
Cuándo conviene rebase
- Tu branch tiene de uno a tres commits y main avanzó. Quieres ponerte al día sin apilar commits de merge en la línea.
- Estás preparando el mensaje final antes de un squash merge.
- El equipo navega el historial con
git log --oneliney busca regresiones congit bisect. Una línea recta acorta las dos búsquedas.
git fetch origin
git rebase origin/main
# hay conflicto: resuélvelo en los archivos y continúa
git add .
git rebase --continue
El historial público no se reescribe
Pro Git abre una sección titulada "Do not rebase public history" con una regla sin excepciones: si otro desarrollador ya hizo pull de los commits que reescribiste, el rebase obliga a un force push y parte el historial en dos. Cada lado trabaja sobre una versión distinta del mismo commit, y el siguiente git pull los mezcla.
Reescribe commits que solo tú has hecho pull. Un branch que otras personas leen recibe merge. Cuando un rebase sale mal, git reflog guarda los commits descartados durante días y git rebase --abort te devuelve al punto de partida.
Squash merge
Un squash merge comprime todos los commits de la feature en uno solo antes de entrar en main. Main se vuelve una línea con un commit por feature, y la discusión del PR conserva el detalle que el mensaje del commit deja fuera.
Los equipos que aplastan renuncian a la secuencia de intentos dentro del branch. A cambio, el git log de main se lee como un changelog. El arreglo en el que terminan la mayoría: commits chicos en el branch, squash al momento del merge.
git checkout main
git merge --squash feature-branch
git commit -m "feat(auth): add JWT refresh token rotation"
El flujo completo
# 1. branch nuevo desde main actualizado
git checkout main && git pull
git checkout -b feature/user-validation
# 2. commits locales mientras trabajas
git add . && git commit -m "feat: add user model"
git commit -m "feat: add validation logic"
# 3. antes del PR, ponte al día con main
git fetch origin
git rebase origin/main
# 4. conflicto: resuélvelo y continúa
git rebase --continue
# 5. push y PR, con squash merge habilitado en el repositorio
Rebase mantiene el branch al día hasta que abre el PR. Squash merge mantiene main legible después de que entra. Los dos comandos ocupan momentos distintos del flujo.
Referencias
- Pro Git, capítulo 3.6: Rebasing (Scott Chacon y Ben Straub, Apress)
- git-rebase y git-merge (documentación oficial de Git)
- Configuring pull request merges (GitHub Docs)
¿Te gustó el contenido?
Construyo productos web y soluciones con IA de la manera correcta — arquitectura sólida, código sostenible y entrega real.
Hablemos