Table of Contents
3 Escenarios Comunes y Frustrantes
Cuando usas Git, tu historial de commits a veces puede volverse complejo sin que te des cuenta. Aquí tienes algunos escenarios clásicos que muchos desarrolladores han enfrentado.
Escenario 1: Crear una rama desde otra rama de funcionalidad por accidente
Se suponía que debías crear tu nueva rama de trabajo (mi-feature) desde la última versión de main, pero accidentalmente la creaste a partir de una rama en la que un colega está trabajando (dev-feature). Ahora tu Pull Request incluye commits que no tienen nada que ver con tu trabajo.
|
1 2 3 4 5 6 7 8 9 |
# [Estado del Problema] * commit C (HEAD -> mi-feature) * commit B * commit A (dev-feature) <-- No debería haber creado la rama desde aquí | * Último main (main) |/ * ... |
Escenario 2: Mezclar múltiples funcionalidades en una sola rama
Mientras trabajabas en una rama (rama-de-trabajo), te das cuenta de que los commits C y D en realidad pertenecen a una funcionalidad completamente diferente (nueva-idea). Quieres separar limpiamente solo estos dos commits en una nueva rama.
|
1 2 3 4 5 6 7 8 9 10 |
# [Estado del Problema] * commit E (HEAD -> rama-de-trabajo) * commit D ┓ * commit C ┛ <-- Quiero separar solo estos dos * commit B * commit A * Último main (main) * ... |
Escenario 3: Empezar un trabajo nuevo sobre una rama desactualizada
Comenzaste un nuevo trabajo (trabajo-nuevo) en una rama que creaste hace meses (feature-antigua). Mientras tanto, la rama main ha evolucionado significativamente, y tus nuevos commits ahora están sobre un historial muy antiguo.
|
1 2 3 4 5 6 7 8 9 10 11 |
# [Estado del Problema] * commit Y (HEAD -> trabajo-nuevo) * commit X | * Un main mucho más reciente (main) | | * ... | |/ | * commit B (feature-antigua) <-- Base desactualizada |/ * Un commit antiguo de main |
Todos estos problemas se pueden resolver con git rebase --onto.
La Clave de la Solución: ¿Qué es git rebase --onto?
git rebase --onto es un comando de rebase muy potente que te permite especificar exactamente qué commits mover (desde..hasta) y a dónde moverlos (onto).
Sintaxis Básica del Comando
|
1 |
git rebase --onto <nueva-base> <antigua-base> <rama-a-mover> |
Entender estos tres argumentos es la clave para dominar este comando.
Guía Práctica: Comandos para Cada Escenario
Escenario 1: Crear una rama desde otra rama de funcionalidad
Veamos un ejemplo concreto para el caso más común: «Escenario 1: Crear una rama desde otra rama de funcionalidad por accidente».
Objetivo: Reorganizar la rama mi-feature para que se origine desde main en lugar de dev-feature.
|
1 2 3 4 5 6 7 |
# Explicación: # --onto main <-- La nueva base es "main" # dev-feature <-- La antigua base es "dev-feature". Los commits posteriores a este punto se moverán. # mi-feature <-- La rama cuyos commits queremos mover es "mi-feature". git rebase --onto main dev-feature mi-feature |
Con este único comando, Git reconstruye el historial de la siguiente manera:
|
1 2 3 4 5 6 7 8 9 10 |
# [Estado Ideal Después del Rebase] * commit C' (HEAD -> mi-feature) * commit B' | * Último main (main) | | * commit A (dev-feature) | |/ |/ * ... |
Los commits de mi-feature (B’ y C’) se han movido limpiamente sobre main, y ahora son independientes de dev-feature.
Escenario 2: Separar commits de una rama
Objetivo: Mover los commits C y D de rama-de-trabajo a una nueva rama nueva-idea, basada en main. En este caso, usamos los IDs de los commits directamente.
|
1 2 3 4 5 6 7 8 9 10 |
# Obtén el ID del commit padre del rango que quieres mover. git log --oneline rama-de-trabajo # Copia el ID del commit B (el padre de C) # 1. Crea una nueva rama en la posición actual git switch -c nueva-idea rama-de-trabajo # 2. Usa rebase --onto para mover los commits # --onto [nueva-base] [padre-del-rango] [final-del-rango] git rebase --onto main <ID_del_commit_B> <ID_del_commit_D> |
Esto colocará solo los commits C y D (como nuevos commits) sobre la rama main en tu nueva rama nueva-idea.
Escenario 3: Mover de una base antigua a la base más reciente
Objetivo: Mover la rama trabajo-nuevo desde su base desactualizada (feature-antigua) a la punta de la versión más reciente de main.
|
1 2 3 |
# --onto [nueva-base] [antigua-base] [rama-a-mover] git rebase --onto main feature-antigua trabajo-nuevo |
La estructura del comando es idéntica a la del Escenario 1. rebase --onto funciona perfectamente, sin importar cuán separadas estén las ramas.
Consejos y Trucos de Seguridad Importantes
Hacer Push a un Repositorio Remoto
El rebase reescribe tu historial de commits local. Si haces rebase a una rama que ya ha sido subida a un repositorio remoto, debes evitar git push --force, ya que puede causar problemas a tus compañeros. En su lugar, usa la opción más segura --force-with-lease.
|
1 2 3 |
# Haz un push forzado asegurándote de no sobrescribir el trabajo de otra persona git push --force-with-lease origin <nombre-de-la-rama> |
Manejar Conflictos Durante un Rebase
Dado que un rebase aplica los commits uno por uno, es posible que encuentres un conflicto de merge. No te asustes; sigue estos pasos para resolverlo.
- Resuelve los conflictos en los archivos: Abre los archivos en tu editor y corrige el código, eliminando los marcadores
<<<<<<<,=======, y>>>>>>>. - Añade los archivos resueltos al «staging area»:
1git add <ruta/al/archivo/resuelto> - Continúa con el rebase:
1git rebase --continue
Si te sientes abrumado y quieres detener el rebase, siempre puedes volver al estado anterior al inicio con este comando:
|
1 |
git rebase --abort |
Conclusión
git rebase --onto puede parecer complejo al principio, pero una vez que entiendes el concepto de «mover este rango de commits a esa nueva base», se convierte en una herramienta poderosa para ordenar tu historial de Git.
Si alguno de los escenarios descritos aquí te resulta familiar, prueba este comando. Solo recuerda comunicarte con tu equipo cuando reescribas el historial de una rama compartida.
