Git desde Cero: Manejo de ramas.

Publicado el 18 julio 2013 por Codehero @codeheroblog

Bienvenidos a un nuevo capítulo de Git desde cero en este curso hablaremos sobre como manejar las ramas en un proyecto y cuales son las mejores prácticas. Los comandos a utilizar esta semana serán los siguientes:

  • git checkout -b
  • git branch -d
  • git merge
  • git branch (múltiples comandos.)

nota: hemos creado un repositorio en Github con el curso para que descargues lo que hemos realizamos durante éste curso y le eches un vistazo.


¿Qué es una rama?

Sí recordamos el primer capítulo de git desde cero sabemos que cuando consolidamos cambios, creamos una fotografía del estado actual de la información que se encuentra en escenario, luego se descartaban los archivos que no tenían modificaciones y se reverenciaban al estado anterior. Al verificar el estado anterior se comprueba quién es o son padres directos de esta fotografía. Es decir, se busca cuales son los cambios que fueron consolidados antes que este y se les referencia como el padre directo. Siguiendo este modelo, lo primero que consolidamos en el proyecto no tiene padre, los cambios consolidados sobre la rama principal tienen un único padre, y los cambios que provienen de la unión de una o más ramas tienen múltiples padres.

Entonces, retomando ¿Qué es una rama? Una rama es una extensión del árbol o tronco principal. Como buena práctica dentro de las ramas del árbol es donde deberíamos introducir los cambios a nuestro proyecto y solo luego de comprobar que dichos cambios funcionan y tienen el comportamiento deseado los unimos con el árbol principal. Esto es porque queremos que el árbol se encuentre lo más limpio posible.

Para comprender esto es necesario realizar un ejemplo.

En la foto apreciamos que es un árbol en línea recta que no presenta ramificaciones. >

Para poder explicar el curso realizaremos los siguientes pasos:

  • Crearemos una rama, trabajaremos sobre ella y guardaremos los cambios.
  • Nos devolveremos a la rama principal y crearemos otra rama.
  • Trabajaremos sobre esta rama, luego guardaremos los cambios y la uniremos con la rama principal.
  • Iremos a la primera rama creada, realizaremos cambios y los guardaremos.
  • Trataremos de unir esta primera rama con la principal y resolveremos los conflictos creados.

De esta manera se comprenderá el uso de todos los comandos de este curso.


Checkout -b

El comando checkout -b es el comando corto para crear una nueva rama y cambiarnos a la misma.

$ git checkout -b primera-rama
# hemos creado la nueva rama y nos cambiamos
Switched to a new branch 'primera-rama'

Sobre esta nueva rama introduciremos un cambio sobre el archivo README.md

$ nano README.md 

# Agregamos el siguiente texto.
Este repositorio conserva absolutamente todo el historial del curso.
Se encuentra clasificado por capítulos almacenados en etiquetas (tags), para
poder observar estos cambios debes revisar el log.

Guardamos el archivo y consolidamos los cambios.

$ git add README.md
$ git commit -m "Agregar párrafo al README"

Una vez consolidados los cambios nos movemos nuevamente al árbol principal y posteriormente creamos una nueva rama.

$ git checkout master
$ git checkout -b segunda-rama

# observamos la salida

Switched to a new branch 'segunda-rama'

En este momento si entramos al archivo README.md podremos observar que su estado es el mismo del árbol principal y no tiene la información del párrafo que agregamos en la primera rama. Vamos a agregar un pequeño cambio a este archivo y luego los consolidaremos.

$ nano README.md

# Agregamos el siguiente texto
Para ir a un capítulo utilizamos:

    $ git tag -l
    $ git checkout Capitulo-X  # Donde X es el número del capítulo.
    
# Subimos los cambios al escenario y los consolidamos.

$ git add README.md
$ git commit -m "Agregar modificación al archivo README"

En este momento el árbol comienza a presentar una ramificación debido a que existen dos ramas en la cabeza del árbol. Donde solo una de ellas se encuentra de manera “lineal”.


Merge

El comando merge es empleado para realizar la unión de dos ramas. Se debe tener cuidado cuando se realiza el merge ya que es muy probable que ocurran conflictos al ejecutarlo. Los conflictos ocurren cuando se trata de realizar la unión (merge) de dos archivos. Éstos dos archivos vienen siendo el mismo pero en ramas diferentes y pueden presentar discrepancia cuando se comparan línea a línea; de esto ocurrir estamos presenciando un conflicto.

Realizaremos el merge de la segunda rama con el árbol principal. No existirá conflicto alguno. Para realizar la unión de dos ramas debemos estar ubicados en la rama a la que se le quieren agregar los cambios, en este caso “master” y luego aplicar la unión.

$ git checkout master
$ git merge segunda-rama

# Podemos apreciar que la unión se realizó correctamente y sin conflictos.
Updating 0022f43..bc8fc31
Fast-forward
 README.md | 5 +++++
 1 file changed, 5 insertions(+)

Branch -d y -D

Una vez que unimos la rama y hemos aplicado el cambio correctamente es buena práctica eliminar la rama donde trabajamos, es decir “segunda-rama” y la eliminamos con el siguiente comando:

$ git branch -d segunda-rama 
Deleted branch segunda-rama (was bc8fc31).

Utilizando la bandera “-d” eliminamos la rama unicamente si esta se ha unido. de lo contrario nos arrojará un error. Si queremos desechar la rama completa sin importar la unión utilizamos “-D” como bandera. >


Resolver conflictos

Uniremos la “primera-rama” y la rama principal “master” luego de haber unido los cambios de la “segunda-rama“. Cuando git realice la comparación línea a línea encontré discrepancias y nos indicará que han ocurrido conflictos. Hagamos la prueba:

$ git checkout master
$ git merge primera-rama

# Ocurrió un conflicto
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Automatic merge failed; fix conflicts and then commit the result.

Para resolver este conflicto basta con abrir el archivo con problemas(en nuestro caso README.md) buscar <<<<< >>>>> este tipo de flechas y rayas ====== eliminarlas y ajustar el código o texto adecuadamente.

Acomodamos el texto como más nos guste.

Revisamos el “status” de los archivos y apreciamos lo siguiente:

$ git status
# On branch master
# Your branch is ahead of 'origin/master' by 1 commit.
#   (use "git push" to publish your local commits)
#
# You have unmerged paths.
#   (fix conflicts and run "git commit")
#
# Unmerged paths:
#   (use "git add 

Nos dice que tenemos que hacer un “commit” para consolidar el “merge” de la unión de las dos ramas. Por otro lado también nos indica que el archivo README se encuentra modificado en las dos ramas y fue por esta razón que ocurrió el conflicto.

Consolidamos los cambios.

$ git add README.md
$ git commit -m "Unión de primera-rama con master"

Podemos apreciar que tenemos una rama que crece del árbol principal y posteriormente se vuelve a unir con el árbol, dejando un “lomo” sobre el mismo.


Branch

El comando “branch” en git funciona para el manejo de ramas. Existen muchas variaciones de este comando; aquí enseñaremos las más utilizadas. Cómo lo son git branch encargada de listar todas las ramas, git branch -v encargada de mostrar los últimos comentarios de las consolidaciones que existieron en cada rama. git branch –merge enseña únicamente las ramas que fueron unidas y git branch –no-merge que muestra las ramas no unidas.

$ git branch
* master
  primera-rama
  
$ git branch -v
* master       05fe98e [ahead 3] Unión de primera-rama con master
  primera-rama df0589c Agregar párrafo al README
  
$ git branch --merged 
* master
  primera-rama

Al apreciar las salidas arrojadas de dichos comandos observamos que son las ramas que conocemos y trabajos sobre este capítulo.


Conclusión

En este último capítulo y en conjunto con los cursos anteriores hemos adquirido el conocimiento necesario para utilizar ramas en los proyectos que desarrollemos, éste es un atributo fundamental en el flujo de trabajo de git. Si te surge algún tipo de duda no te detengas y déjanos un comentario, que gustosamente lo responderemos.

¡Hasta la próxima semana!