Saltar al contenido
sudoquest@root
Git

Ramas

Trabajar en varias cosas a la vez sin mezclarlas: crear una rama, cambiar entre ramas, juntarlas con merge y leer el gráfico.

30 min de lectura

El cliente quiere ver la casa con buhardilla. Y con piscina. Y quizá con un garaje. Si todo eso se dibuja sobre el proyecto aprobado, se mezcla, y deshacer lo que no guste es un lío. Las ramas lo resuelven: cada propuesta va en su propia línea de commits, sin tocar las demás, y la que se aprueba se junta con la principal.

En este tema trabajas con Trazo, un estudio de arquitectura que guarda en Git los planos de sus proyectos. Como en los anteriores, cada sección tiene un ejercicio con una terminal.

Crear una rama y cambiarse a ella

git branch enseña las ramas; la de ahora, con un *. Con un nombre, crea una nueva, que apunta al mismo commit que la actual (sin cambiarse a ella):

tecnico@srv-pruebas:~/estudio$ git branch buhardilla
tecnico@srv-pruebas:~/estudio$ git branch
  buhardilla
* main

git switch rama te cambia a ella: los archivos de la carpeta pasan a ser los de esa rama, y los commits que hagas irán a ella.

tecnico@srv-pruebas:~/estudio$ git switch buhardilla
Switched to branch 'buhardilla'

Las dos cosas a la vez: git switch -c rama (crear y cambiarse). Antes de switch se usaba git checkout rama y git checkout -b rama, que siguen funcionando y verás en muchas guías.

Tras un commit en buhardilla, cada rama apunta a lo suyo:

tecnico@srv-pruebas:~/estudio$ git log --oneline --all
b309db4 (HEAD -> buhardilla) La buhardilla
10a2b50 (main) El proyecto básico

--all enseña todas las ramas, no solo la actual. Y al volver a main, el plano de la buhardilla no está en la carpeta: es de la otra rama.

tecnico@srv-pruebas:~/estudio$ git switch main
Switched to branch 'main'
tecnico@srv-pruebas:~/estudio$ ls planos
planta-baja.txt

Ejercicio

Una rama para la propuesta

El cliente quiere ver cómo quedaría la casa con buhardilla, sin tocar el proyecto aprobado (main). Haz una rama buhardilla, cámbiate a ella y guarda allí el plano planos/buhardilla.txt (con "estudio 20" y "bano 4", una cosa por línea).

Preparando la máquina…

Cambiar de rama con cambios sin guardar

Si tienes cambios sin guardar, Git se los lleva contigo al cambiar de rama, siempre que el archivo sea igual en las dos (y lo dice: M y el archivo):

tecnico@srv-pruebas:~/estudio$ git switch -c prueba
M	planos/planta-baja.txt
Switched to a new branch 'prueba'

Si el archivo es distinto en la otra rama, cambiar pisaría tu trabajo, y Git no te deja:

tecnico@srv-pruebas:~/estudio$ git switch garaje
error: Your local changes to the following files would be overwritten by checkout:
planos/planta-baja.txt
Please commit your changes or stash them before you switch branches.
Aborting

¿Ya lo guardaste en main y era de otra rama? Como una rama es solo un nombre, git branch rama crea una ahí mismo, con ese commit dentro; después, en main, git reset --hard HEAD~1 (tema 2) lo quita de main, y la rama lo conserva.

Ejercicio

Cambiar de rama sin mezclar

Estás en la rama piscina, con la memoria a medio escribir (sin guardar). Urge corregir el presupuesto en main: las instalaciones son 22000. Guarda tu trabajo en piscina, cámbiate a main, corrige y guarda; lo de la piscina no puede llegar a main.

Preparando la máquina…

Juntar: git merge (fast-forward)

git merge rama junta esa rama con la actual. Si la actual no ha cambiado desde que salió la otra, no hace falta mezclar nada: la rama actual simplemente avanza hasta la otra (fast-forward):

tecnico@srv-pruebas:~/estudio$ git merge buhardilla
Updating 10a2b50..b309db4
Fast-forward
planos/buhardilla.txt | 1 +
1 file changed, 1 insertion(+)
create mode 100644 planos/buhardilla.txt

Siempre se junta en la rama en la que estás: para llevar buhardilla a main, primero git switch main. Si ya estaba todo, Git dice Already up to date.

Ejercicio

Main, al día

La rama garaje tiene dos commits que el cliente ya ha aprobado, y main no ha cambiado desde que se creó. Junta garaje con main.

Preparando la máquina…

Juntar dos ramas que han avanzado: el commit de merge

Si las dos ramas tienen commits nuevos, no basta con avanzar: Git hace un commit nuevo con dos padres que junta lo de las dos (la estrategia se llama ort). Para el mensaje abre el editor con uno ya escrito (Merge branch 'piscina'); con --no-edit lo usa sin preguntar:

tecnico@srv-pruebas:~/estudio$ git merge --no-edit piscina
Merge made by the 'ort' strategy.
planos/jardin.txt | 1 +
1 file changed, 1 insertion(+)
create mode 100644 planos/jardin.txt

Si las dos ramas cambiaron lo mismo (las mismas líneas de un archivo), Git no sabe con cuál quedarse: es un conflicto, y eso es el tema 4. Con --no-ff, Git hace el commit de merge aunque pudiera avanzar, para que quede a la vista que ahí se juntó una rama.

¿Juntaste la que no era? git reflog (tema 2) dice dónde estaba main antes del merge, y git reset --hard a ese commit la devuelve allí; la otra rama no se toca, y sigue sin juntar.

Ejercicio

Juntar dos ramas que han avanzado

El cliente aprueba la piscina. Pero mientras se dibujaba, en main también se guardó algo (el presupuesto nuevo). Junta piscina con main: un commit que lleve lo de las dos.

Preparando la máquina…

Borrar las ramas que ya no hacen falta

Una rama ya juntada sobra: su trabajo está en main. git branch --merged dice cuáles lo están, y git branch -d rama la borra:

tecnico@srv-pruebas:~/estudio$ git branch -d buhardilla
Deleted branch buhardilla (was b309db4).

Si no está juntada, -d no la borra (perderías sus commits); -D sí, si de verdad sobran:

tecnico@srv-pruebas:~/estudio$ git branch -d sotano
error: The branch 'sotano' is not fully merged.
If you are sure you want to delete it, run 'git branch -D sotano'.

Borrar una rama solo borra el nombre: sus commits siguen ahí un tiempo. Si al final no sobraba, git branch sotano <hash> la vuelve a crear tal como estaba, con el hash que dijo Git al borrarla (was …); y si no lo viste, git reflog (tema 2) apunta por dónde ha pasado HEAD, también por sus commits. Lo mismo vale para main, si un reset de más la deja sin lo aprobado.

Otras: git branch -m vieja nueva la renombra; git branch -v, con su último commit; git branch --no-merged, las que aún no están juntadas.

Ejercicio

Ramas que ya no hacen falta

En el estudio se acumulan ramas: las ya juntadas con main sobran, pero sotano aún no se ha juntado (el cliente no ha decidido). Borra las que ya están en main y deja sotano.

Preparando la máquina…

El gráfico: git log –graph

Con varias ramas, el historial ya no es una línea. git log --oneline --graph --all lo dibuja: cada * es un commit, y las líneas, por dónde va cada rama; |\ es donde un merge junta dos y |/ donde una rama salió de otra.

tecnico@srv-pruebas:~/estudio$ git log --oneline --graph --all
*   71e085b (HEAD -> main) Merge branch 'piscina'
|\  
| * f3f2ccb (piscina) La piscina
* | b309db4 (buhardilla) La buhardilla
|/  
* 10a2b50 El proyecto básico

Se lee de arriba abajo, de lo más nuevo a lo más viejo. Y para comparar ramas: git log main..piscina enseña los commits de piscina que aún no están en main.

Ejercicio

Leer el gráfico

De las tres propuestas (ventanales, porche y chimenea), una aún no está en main. Mírala en el gráfico del historial y apunta su nombre en ~/respuesta.txt.

Preparando la máquina…

El HEAD suelto (detached HEAD)

git switch (o checkout) a un commit, no a una rama, deja HEAD suelto: miras cómo era el proyecto entonces, pero no estás en ninguna rama. Git lo avisa con un mensaje largo:

tecnico@srv-pruebas:~/estudio$ git checkout HEAD~1
Note: switching to 'HEAD~1'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.
…
HEAD is now at b309db4 La buhardilla

Los commits que hagas así no son de ninguna rama: al volver (git switch main), Git avisa de que se quedan atrás. Para quedártelos, crea una rama ahí mismo: git switch -c nueva.

Resumen

Orden Qué hace
git branch (-v, -a) las ramas, y en cuál estás
git branch nombre crea una rama (sin cambiarse)
git switch rama / git switch -c rama cambiarse / crearla y cambiarse
git checkout rama / checkout -b rama lo mismo, la forma antigua
git merge rama junta esa rama con la actual (avanza o hace un commit de merge)
git merge --no-edit / --no-ff sin editor / siempre con commit de merge
git branch -d rama / -D borra una rama juntada / aunque no lo esté
git branch --merged / --no-merged las juntadas / las que no
git log --oneline --graph --all el historial de todas las ramas, dibujado
git log a..b lo que tiene b y no tiene a