Skip to content
This page has been auto-translated and may contain errors.View in English

Ramas en Git

docs.scrimba.com

Estás a mitad de camino construyendo weather-app y quieres intentar agregar una función de pronóstico de cinco días. Podría tomar varios commits para hacerlo bien, y hasta que no lo logres, no quieres código a medio terminar sentado junto a la aplicación que ya funciona para todos los que la usan. Una rama es cómo Git resuelve esto: una línea de trabajo separada donde el experimento vive, mientras que main sigue funcionando exactamente como lo hacía antes de que comenzaras.

Qué es realmente una rama

Aquí está en acción:

bash
$ git branch forecast
$ git switch forecast
Switched to branch 'forecast'

Dos comandos: el primero crea una nueva rama llamada forecast, el segundo te mueve a ella. Desde aquí, cada commit que hagas aterriza en forecast mientras main se queda exactamente donde está.

Una rama es una etiqueta movible que apunta a un commit. Ahora mismo, main y forecast apuntan al mismo commit, el que estabas ocupando cuando ejecutaste git branch forecast. En el momento en que commits nuevamente mientras estés en forecast, esa etiqueta se mueve hacia adelante al nuevo commit. main se queda exactamente donde estaba hasta que cambies a ella y hagas commit allí tú mismo.

Puedes ver ambas etiquetas con git branch:

bash
$ git branch
  forecast
* main

El asterisco marca la rama en la que te encuentras actualmente. Una rama es solo un nombre que apunta a un commit. Ese es todo el mecanismo. Todo lo demás en este capítulo es una variación de mover esas etiquetas.

En un proyecto real, los nombres de las ramas llevan información. Una convención común es un prefijo corto describiendo el tipo de cambio, seguido de una descripción: feature/five-day-forecast, fix/broken-date-picker, chore/upgrade-eslint. Algunos equipos agregan un número de ticket (feature/wa-142-forecast). Sea cual sea la convención que elijas, mantenla consistente en todo el proyecto para que cualquiera pueda saber para qué es una rama sin abrirla.

El flujo de trabajo que esos nombres soportan son ramas de características de corta duración: crea una rama para una pieza de trabajo, commit a ella, obtén que el cambio sea revisado y fusionado, luego borra la rama. Una rama que vive por semanas se aleja mucho de main, y la eventual fusión se vuelve más difícil cuanto más tiempo continúe ese distanciamiento. Las ramas más saludables terminan dentro de días.

Una rama es apenas más que un archivo diminuto que contiene un hash de commit, guardado dentro de la propia contabilidad de Git. Crear una significa escribir esa única línea, razón por la cual git branch termina instantáneamente incluso en un repositorio con años de historial detrás. Esa misma economía es por qué las convenciones de nombres y las ramas de corta duración importan en la práctica: borrar una rama obsoleta no le cuesta nada a Git tampoco, así que nada impide que se acumulen las abandonadas excepto la propia disciplina del equipo.

JunoQué es realmente una ramagit branch forecast crea una nueva etiqueta que apunta a tu commit actual, y git switch forecast te mueve a ella. Nada sobre tus archivos cambia hasta que realmente hagas commit allí. Me gusta imaginar las ramas como notas adhesivas en un commit: baratas de agregar, baratas de mover, baratas de despegar cuando terminas.
JunoQué es realmente una rama Un nombre de rama es un puntero, así que crear una no cuesta nada y cambiar entre ellas es instantáneo. Dale a las ramas nombres que describan el trabajo, como feature/five-day-forecast, y mantenlas de corta duración: crea, commit, fusiona, borra. Las ramas de larga duración son las que convierten una fusión rutinaria en un dolor de cabeza real.
JunoQué es realmente una rama Una rama realmente es un pequeño archivo que contiene un hash de commit, razón por la cual crear una es una de las operaciones más baratas en Git. Las convenciones de nombres y las ramas de corta duración son cómo un equipo mantiene su trabajo paralelo legible; Git en sí no impone nada de esto. He limpiado suficientes ramas abandonadas de hace seis meses como para tener opiniones fuertes al respecto.

Crear y cambiar entre ramas

git branch forecast por sí solo crea la etiqueta sin moverte allí. La mayoría de las veces quieres ambas cosas a la vez, así que git switch tiene un atajo:

bash
$ git switch -c forecast
Switched to a new branch 'forecast'

-c significa "create" (crear). git switch -c crea y te mueve a una rama. Ese comando único es el que usarás casi cada vez que comiences un nuevo trabajo.

Cambiar ramas cambia qué snapshot tus archivos muestran. Pruébalo: la línea echo a continuación es una forma de un paso para crear un nuevo archivo, src/forecast.js, con una única línea en él, y todo lo demás son comandos que ya conoces:

bash
$ git switch forecast
$ echo "// lógica de pronóstico de cinco días" > src/forecast.js
$ git add src/forecast.js
$ git commit -m "Start forecast module"
$ ls src
forecast.js  index.js
$ git switch main
Switched to branch 'main'
$ ls src
index.js

El archivo no ha desaparecido. Vive en la rama forecast, y el snapshot de la rama main nunca lo incluyó. Cambia de nuevo a forecast y reaparece exactamente como lo dejaste.

Verás un verbo más antiguo para esto en código y tutoriales existentes: git checkout forecast hace el mismo trabajo que git switch forecast. checkout es más antiguo y hace más de una cosa: dependiendo de lo que le des, puede cambiar ramas o restaurar un archivo a una versión anterior, y el nombre del comando solo no te dice cuál está a punto de suceder. switch y restore dividen esos dos trabajos en comandos separados para que el nombre te lo diga por adelantado: switch te mueve entre ramas, restore devuelve un archivo a cómo se veía en un commit dado. Usa los verbos más nuevos; reconoce checkout cuando lo encuentres en la naturaleza.

checkout decide qué hacer basándose en lo que le das: un nombre de rama cambia ramas, una ruta de archivo restaura ese archivo, y si un nombre coincide con ambos, Git tiene que adivinar cuál quisiste decir. Esa adivinanza es exactamente por qué el comando se dividió en dos. switch solo cambia ramas y restore solo cambia archivos, así que una ruta mal escrita ya no puede cambiarte a una rama por accidente. Espera checkout en scripts y tutoriales más antiguos durante años más; escribe switch y restore en cualquier cosa nueva.

JunoCrear y cambiar entre ramasgit switch -c forecast crea una rama y te mueve a ella en un paso, que es lo que usarás casi cada vez. Cambiar ramas intercambia qué versión de tus archivos ves, así que un archivo agregado en una rama está ausente en otra hasta que cambies de vuelta. Nada se pierde, está estacionado en la otra rama.
JunoCrear y cambiar entre ramasgit switch -c name crea y se mueve en un paso. Encontrarás git checkout name haciendo el mismo trabajo en tutoriales y bases de código más antiguos; es la misma idea bajo un comando más antiguo y más sobrecargado. Usa switch día a día y lee checkout sin dudarlo cuando lo veas.
JunoCrear y cambiar entre ramascheckout maneja tanto el cambio de rama como la restauración de archivos dependiendo de sus argumentos, que es exactamente la ambigüedad que switch y restore fueron separados para eliminar. Espera leer checkout en scripts y tutoriales más antiguos durante años más; todavía funciona, ya no es el comando a escribir por defecto.

HEAD y HEAD separado

Git mantiene un registro de dónde estás actualmente con un marcador llamado HEAD. Normalmente HEAD apunta a tu rama actual, y esa rama apunta a un commit, así que HEAD se mueve automáticamente cada vez que cambias o haces commit. Si accedes a un commit específico por su hash, o una etiqueta (una etiqueta fija fijada a un commit, a menudo marcando un lanzamiento), en lugar de un nombre de rama, HEAD se une directamente a ese commit en lugar de a una etiqueta de rama. Este estado se llama HEAD separado.

Puedes mirar alrededor libremente allí, e incluso puedes hacer commit, pero nada apunta a esos nuevos commits por nombre. Si cambias a una rama sin crear una primero, se vuelven difíciles de encontrar de nuevo.

bash
$ git switch a1b2c3d
HEAD is now at a1b2c3d Add password strength meter

Ese mensaje, "HEAD is now at", es Git diciéndote que has dejado el territorio de rama y has unido HEAD a un único commit.

En el trabajo diario rara vez llegas aquí por accidente. Sucede más a menudo cuando accedes a una etiqueta antigua o a un commit específico para ver cómo se comportaba el código en ese punto, o cuando una herramienta de compilación accede a un commit exacto desde el cual trabajar. Si solo quieres mirar, está bien: navega por los archivos, ejecuta la aplicación, luego cambia a una rama cuando termines. Si haces un cambio que valga la pena mantener mientras estés separado, crea una rama antes de cambiar: git switch -c fix/old-bug desde ese estado separado le da al commit una etiqueta real para que sobreviva al cambio.

Un commit dejado atrás por un HEAD separado no se elimina en el momento en que cambias. Se vuelve inaccesible: aún almacenado, sin rama, etiqueta o HEAD apuntando a él anymore. Git tampoco lo limpia de inmediato. Mantiene un reflog, un registro de dónde ha apuntado HEAD, y un commit inaccesible típicamente sobrevive durante semanas antes de que Git lo elimine para bien.

Eso te da tiempo real para recuperarlo, aunque no dura para siempre. Hacer una rama antes de cambiar mantiene el trabajo separado seguro. Desenterrar un commit del reflog funciona hoy, pero la entrada expira eventualmente y un hash de commit se te escapa de la mente mucho antes de eso, así que haz de la ramificación un hábito y guarda el reflog para la rara vez que olvides, cubierto en Deshaciendo cosas.

JunoHEAD y HEAD separado HEAD marca el commit en el que estás parado actualmente, y normalmente viaja junto con la rama en la que estés. Si accedes a un commit específico en lugar de a una rama, obtienes un HEAD separado, y cualquier nuevo commit que hagas allí no tiene un nombre de rama apuntando a él. Si eso sucede alguna vez y quieres mantener el trabajo, haz una rama en el acto antes de cambiar a cualquier otro lugar.
JunoHEAD y HEAD separado Lo más probable es que encuentres un HEAD separado cuando accedas a una etiqueta o a un commit antiguo para mirar alrededor, y es inofensivo mientras solo estés leyendo. En el momento en que hagas commit algo que valga la pena mantener, ejecuta git switch -c justo allí para darle una rama antes de que vayas a cualquier otro lugar.
JunoHEAD y HEAD separado Normalmente HEAD apunta a una rama, que apunta a un commit. Separado, HEAD apunta directo al commit, así que cualquier cosa que agregues allí no tiene un nombre de rama sosteniéndola una vez que cambias. Rara vez se desaparece para siempre ya que el reflog mantiene un rastro, pero no cuentes con recordar el hash de commit tres semanas después. Haz la rama antes de cambiar, siempre.

Hacia dónde lleva esto

Ya has creado ramas, te has movido entre ellas, y has visto cómo main se mantiene intacta mientras experimentas en otro lugar. La siguiente pregunta es cómo el trabajo en una rama vuelve a main, que es exactamente lo que Fusionando y conflictos cubre. Si quieres un repaso sobre cómo leer el historial de commits antes de continuar, Historial recorre git log, git show, y git diff.