Ramas en Git: git branch, crear, cambiar y eliminar ramas
Una rama en Git es un puntero ligero a un commit, y HEAD indica en qué rama se encuentra usted ahora. git branch lista, crea, renombra y elimina ramas, y git switch cambia entre ellas; git switch -c nombre crea la rama y se cambia a ella de inmediato.
Qué es una rama en Git
Una rama en Git no es una copia del proyecto, sino un pequeño archivo con el hash de un commit. Crear una rama lleva fracciones de segundo y apenas ocupa espacio, porque Git no duplica nada: todas las ramas apuntan a los mismos objetos de la base de datos del repositorio. Cuando hace un commit, el puntero de la rama actual simplemente avanza al nuevo commit.
Esto cambia la forma de ver las ramas. No hay que tenerles miedo ni ahorrarlas: una rama para cada tarea, corrección o experimento es lo normal. Si el experimento sale mal, se borra la rama y el historial principal queda limpio.
Puede comprobar con sus propios ojos que una rama es un archivo:
$ cat .git/refs/heads/main
8b7d4e2a9f1c0d3e5b6a7c8d9e0f1a2b3c4d5e6f
(En repositorios grandes parte de las referencias se empaqueta en .git/packed-refs, así que el archivo puede no existir; la idea es la misma.)
HEAD en Git: dónde está ahora
HEAD es un puntero a lo que tiene «extraído» en el directorio de trabajo. Normalmente HEAD no apunta a un commit, sino a una rama:
$ cat .git/HEAD
ref: refs/heads/main
La cadena es: HEAD → main → commit. Un nuevo commit tendrá como padre el commit al que apunta HEAD, y después Git moverá la rama a la que apunta HEAD. Por eso los commits «caen» en la rama actual.
Si se cambia directamente a un commit o a una etiqueta (git switch --detach v1.0 o git checkout 3f2a1c9), HEAD apuntará al commit directamente. Ese estado se llama detached HEAD. Revisar código en él es seguro, pero los nuevos commits no quedan ligados a ninguna rama y es fácil perderlos al cambiar. Si empezó a modificar algo, cree una rama ahí mismo: git switch -c fix-from-old-version.
En las expresiones, HEAD sirve como punto de referencia: HEAD~1 es el commit anterior, HEAD~3, tres commits atrás, y HEAD^2, el segundo padre de un commit de merge.
Cómo ver las ramas: git branch
git branch # ramas locales; la actual se marca con *
git branch -v # además, el último commit de cada una
git branch -vv # además, el upstream y si va adelantada/atrasada
git branch -r # ramas remotas (origin/...)
git branch -a # todas las ramas
git branch --show-current # solo el nombre de la rama actual
Ejemplo de salida de git branch -vv:
feature/login 4c1e2d7 [origin/feature/login: ahead 2] Formulario de inicio de sesión
* main 8b7d4e2 [origin/main] Actualizar README
old-spike 1a9b3c0 Experimento con la caché
Aquí se ve que feature/login tiene dos commits sin enviar, main coincide con el servidor y old-spike ni siquiera tiene pareja en el servidor.
Para filtrar ramas sirven git branch --merged (ya fusionadas en la actual: candidatas a eliminar), git branch --no-merged (todavía sin fusionar) y git branch --list 'feature/*' (por patrón).
Cómo crear una rama
Hay dos formas. git branch crea la rama, pero le deja en la actual:
git branch feature/login # desde el commit actual
git branch hotfix v1.2.0 # desde una etiqueta
git branch review 3f2a1c9 # desde un commit concreto
Lo más habitual es crear la rama y cambiarse a ella al momento. Para eso está git switch -c (apareció en Git 2.23) o su equivalente antiguo git checkout -b:
git switch -c feature/login
git switch -c hotfix origin/main # rama nueva a partir del estado actual del servidor
Un buen hábito antes de crear una rama para una tarea es actualizar la base: git fetch y luego git switch -c feature/x origin/main. Así la rama parte del código actual y no de su main local, que quizá lleve tiempo sin actualizarse.
Cómo nombrar las ramas
Convenciones habituales en los equipos: un prefijo según el tipo de trabajo y una descripción corta separada por guiones: feature/user-avatar, fix/login-timeout, chore/update-deps, a veces con el número de la tarea: feature/SHOP-142-cart. No se permiten espacios, ~ ^ : ? * [, dos puntos seguidos ni terminar en .lock.
Cómo cambiar de rama: git switch
git switch main # ir a una rama existente
git switch - # volver a la rama anterior
git switch feature/login # si no existe en local pero sí origin/feature/login,
# Git crea la local y la vincula con la remota
Al cambiar de rama, Git sustituye los archivos del directorio de trabajo por la versión de la rama de destino. Los cambios sin confirmar le acompañan si no entran en conflicto con esa rama. Si chocan, Git se niega:
error: Your local changes to the following files would be overwritten by checkout:
app.js
Please commit your changes or stash them before you switch branches.
Soluciones: hacer commit, guardarlos con git stash (y recuperarlos luego con git stash pop) o llevarse los cambios conscientemente intentando fusionarlos: git switch -m main. La opción --discard-changes descarta las modificaciones; úsela solo si está seguro de que no las necesita.
¿Por qué git switch y no checkout? Checkout sirve tanto para cambiar de rama como para sobrescribir archivos, y por eso es fácil equivocarse. Switch hace una sola cosa, trabajar con ramas, y es más seguro. La comparación detallada entre checkout, switch y restore está en un artículo aparte.
Cómo renombrar una rama
git branch -m new-name # renombrar la actual
git branch -m old-name new-name # renombrar cualquiera
git branch -M main # igual, sobrescribiendo una rama existente
Si la rama ya estaba en el servidor, el renombrado es solo local. Envíe la nueva y elimine la antigua:
git push -u origin new-name
git push origin --delete old-name
Cómo eliminar una rama
git branch -d feature/login # la elimina solo si está fusionada
git branch -D old-spike # la elimina a la fuerza
git push origin --delete feature/login # eliminarla en el servidor
-d le protege de perder trabajo: si la rama tiene commits que no están en la rama actual (o en su upstream), Git se negará con el mensaje «The branch 'x' is not fully merged». -D borra sin preguntar. La rama actual no se puede eliminar: primero cámbiese a otra.
¿Ha borrado de más? Los commits no desaparecen enseguida. Busque el hash del último commit de la rama en git reflog y restáurela: git branch old-spike 1a9b3c0.
Las referencias obsoletas a ramas remotas que ya no existen en el servidor se limpian con git fetch --prune.
Vincular una rama local con una remota
Una rama local puede tener un upstream: la rama remota con la que se compara y sincroniza. Sirve para que git push y git pull funcionen sin argumentos y para que git status indique «ahead/behind».
git push -u origin feature/login # en el primer envío
git branch --set-upstream-to=origin/main main # para una rama existente
git branch --unset-upstream # quitar el vínculo
Fusionar ramas: en resumen
Las ramas se crean para después unirlas. Cuando el trabajo está listo, cámbiese a la rama de destino y fusione la suya en ella:
git switch main
git merge feature/login
Si main no ha avanzado desde que creó la rama, Git hará un fast-forward: simplemente moverá el puntero de main al último commit de la rama, sin commit de merge. Si ambas ramas tienen commits nuevos, habrá una fusión a tres bandas: Git encontrará el ancestro común, comparará ambos lados y creará un commit de merge con dos padres. En los equipos la fusión suele hacerse mediante un pull request en el servidor, y en local solo se trae el main actualizado.
Chuleta de ramas
| Tarea | Comando |
|---|---|
| Listar ramas | git branch -vv |
| Crear una rama | git branch nombre |
| Crear y cambiarse | git switch -c nombre |
| Cambiar de rama | git switch nombre |
| Volver a la anterior | git switch - |
| Renombrar | git branch -m antiguo nuevo |
| Eliminar una rama fusionada | git branch -d nombre |
| Eliminar a la fuerza | git branch -D nombre |
| Eliminar en el servidor | git push origin --delete nombre |
| Ramas que se pueden borrar | git branch --merged |
| Restaurar una rama borrada | git reflog y luego git branch nombre hash |
Errores típicos de principiantes
- Trabajar directamente en main. Si ya hizo commits pero no los envió, cree una rama en el punto actual (
git branch feature/x) y después devuelvamainal estado del servidor:git reset --hard origin/main(compruebe antes que todo está confirmado). - Rama creada desde un main desactualizado. Primero
git fetch, y cree la rama desdeorigin/main. - Commits en detached HEAD. Cree una rama antes de cambiar; si ya cambió, busque los commits en
git reflog. - Ramas de larga duración. Cuanto más tiempo vive una rama por separado, más dolorosa es la fusión. Traiga
maincon regularidad e integre el trabajo en porciones pequeñas.
Las ramas en el trabajo en equipo
Los procesos varían entre equipos, pero casi siempre aparece uno de dos esquemas. En GitHub Flow hay una única rama de larga duración, main, siempre lista para desplegar, y ramas feature cortas que se fusionan mediante pull request tras la revisión y las comprobaciones de CI. Git Flow añade develop, ramas de release y ramas hotfix; es un esquema más pesado, adecuado para productos con releases versionadas poco frecuentes.
Sea cual sea el esquema, hay reglas comunes: una rama, una tarea; la rama vive días, no meses; antes del pull request la rama se actualiza con el main reciente; tras la fusión se elimina tanto en local como en el servidor. La rama principal se protege en la configuración del repositorio: se prohíben el push directo y el force push, y solo se fusiona tras revisión.
Cómo ver el historial de las ramas
La forma más fácil de entender cómo se relacionan las ramas es con el grafo: git log --oneline --graph --all dibuja todas las ramas y sus puntos de divergencia en la propia terminal. Para ver los commits que están en una rama pero aún no han llegado a main, use git log main..feature/login, y para la diferencia en archivos, git diff main...feature/login (los tres puntos comparan con el ancestro común, es decir, muestran solo los cambios de la propia rama).
Conclusión
Una rama en Git es un puntero barato a un commit, y HEAD es el puntero a la rama actual. git branch gestiona las ramas (listar, crear, renombrar, eliminar), git switch cambia entre ellas y git switch -c hace ambas cosas a la vez. Ramas, HEAD, fast-forward y la fusión a tres bandas se trabajan con ejemplos reales en el curso de Git.
Preguntas frecuentes
¿Cuántas ramas se pueden crear en Git?
Prácticamente las que quiera: cada rama es una referencia de unas decenas de bytes, así que no hay límite de tamaño.
¿Se eliminan los commits al borrar la rama?
No inmediatamente. Los commits a los que ya nada apunta se conservan un tiempo y son accesibles con git reflog hasta que el recolector de basura los elimine (por defecto, no antes de 30 días para las entradas de reflog inalcanzables).
¿Cómo sé desde qué rama se creó la actual?
Git no lo guarda: la rama solo recuerda su commit. El ancestro común con main se encuentra con git merge-base HEAD main.
¿En qué se diferencia una rama de una etiqueta?
La rama avanza con cada commit nuevo, mientras que la etiqueta queda fijada para siempre a un commit y se usa para marcar releases.
¿Por qué main y no master?
Es solo el nombre de la rama por defecto. Muchos servicios han pasado a main; para los repositorios nuevos se configura con git config --global init.defaultBranch main.
Este tema se explica a fondo y con práctica en el curso «Git desde cero hasta desarrollador seguro».
Ir al curso