4. Git References: Best Practices, Tips & Tricks

Updated: 3 days ago

¿Referencias? Sabes cómo funcionan y ¿para qué sirven? Acá encontrarás los mejores ejemplos y tips. 4to y último post de la miniserie de Melt: Git Tricks

Recopilamos para ti algunos tips útiles de Git! En este post aprenderás sobre las referencias y todas las formas en las que Git las implementa.


Si queremos manipular objetos en Git, es importante tener encuenta que todos los objetos de Git son creados bajo un hash SHA-1 (un número hexadecimal único). Con ayuda de este número, todos los comandos de Git pueden ejecutarse dirigiéndose al hash de cada objeto y realizando operaciones entre ellos, pero (obviamente) debes conocer el hash de cada objeto.


Para evitar tener que memorizar estos hashes, Git usa referencias. Que son simplemente un archivo almacenado en el folder .git/refs, el cual contiene el hash de un objeto de commit.


En la carpeta refs/ Git crea un conjunto de nombres o referencias para commits específicos. Donde, por ejemplo, la referencia HEAD apunta al commit más reciente en el archivo actual, la rama apuntaría al commit (detalles más adelante) y al mismo tiempo HEAD puede ser commit.


Con estas referencias, Git implementa un sistema de ramificaciones (branches) que promueve el ciclo de desarrollo al crear ramas de trabajo paralelas y posteriormente, unirse entre sí. Para entender cómo funcionan las ramas en Git, primero debemos conocer la estructura de los datos.


Recuerda que:

Este post hace parte de una miniserie de Melt, y es probable que algunos temas ya hayan sido explicados. Así que, te invitamos a revisar los posts anteriores:



GIT TRICKS

TALK DE LA SEMANA



Repasando

Git almacena una copia de todos los archivos y carpetas tal y como se encuentran en ese momento, esto sucede cada vez que realiza una instantánea o confirmación. Dicha instantánea contiene varios apuntadores que son los commits de los cambios que se realizaron.


Luego de un commit, en el repositorio de Git encontraremos: un blob para cada archivo, un árbol con sus respectivas relaciones con los blobs, una confirmación de cambios (commit) apuntando a la raíz del árbol y la rama apuntando al commit, que por defecto es la rama "master".


Entonces, las refs son ramas o branches?

En Git una rama es simplemente otro apuntador a un commit (si ya sé, todo aquí parece ser un apuntador), sólo que este apuntador se mueve, es decir, la rama que creamos apuntará siempre a un commit y a medida que se agreguen más commit la rama se irá moviendo al más reciente.


Si revisamos el log de nuestro repositorio de Git:

git lola

c5a401b (HEAD -> master)Add new file in folder (5mins ago)<Manuel>
aaaf96c Cambios al readme (11mins ago) <Manuel>
adc8bd2 Added readme, Initial commit (16mins ago) <Manuel>

Puedes ver que HEAD esta apuntando a la rama master y al commit más reciente. Si en el repositorio te devuelves a un commit anterior, así mismo lo hará el apuntador.



Qué es HEAD?

HEAD es una referencia simbólica (es como un acceso directo) a refname: a la rama, al commit, o es directamente un commit.

Sus características:

  • HEAD es un apuntador, carece de información propia

  • HEAD siempre nombra el commit actual

  • HEAD se puede convertir en commit

  • HEAD también referencia a la rama


Suena complicado, pero en el siguiente mini-video te explicamos HEAD de la forma más sencilla:

Si existe algún error en el reproductor, puedes ver el video en el siguiente LINK.


Otra forma de confirmarlo, es como dice el video, revisar la carpeta de referencias de git.

less .git/refs/heads

master

Primero debemos crear una nueva rama de nombre, por ejemplo, "melt".

git checkout -b melt

Luego, cambiarnos a la nueva rama melt, con:

git checkout melt

Y revisar de nuevo la carpeta de referencias:

tree .git/

.git 
└── refs 
|   └─ heads
|   |   └─ melt
...

Una rama es un nombre que apunta al mismo commit que HEAD.



Entonces las ramas terminan siendo referencias, pero no al revés porque no es cierto decir que: todas las referencias son ramas.


Otro caso de refs, etiquetas o tags

Una etiqueta es un tipo de objeto de Git que apunta a un commit (al igual que una rama), pero permaneciendo siempre fijo o inmóvil, es decir, siempre apuntará al mismo commit.



Probémoslo, vamos a ponerle un tag a este commit:

adc8bd2 Added readme, Initial commit (16mins ago) <Manuel>

Creamos una referencia agregando el nombre "el commit inicial" al hash SAH-1 completo del commit:

git update-ref refs/tags/el_commit_inicial adc8bd279064ef2bc91...

Y si revisamos el log, podemos visualizar la etiqueta del commit:

glog

c5a401b (HEAD -> master) Add new file in folder
aaaf96c (melt) Cambios al readme
adc8bd2 (tag: el_commit_inicial) Added readme, Initial commit

Etiquetas Anotativas

Es el mismo tipo objeto de Git, pero en lugar de apuntar directamente a un commit, lo que hace es crear una referencia tipo etiqueta y apuntar a esta y que esta apunte al commit.

git tag -a v1.0 -m 'Version 1.0'

Revisemos de nuevo el árbol de .git/:

tree .git/

.git 
└── refs 
|   └─ heads
|   |   └─ melt
|   └─ tags
|   |   └─ el_commit_inicial
|   |   └─ v1.0
...

Podemos ver que la etiqueta está creada, pero no podemos ver la diferencia entre este objeto y el primero. Así que revisaremos cada uno.


Empezando con el primer tag, encontramos que apunta a un hash que ya conocemos de los ejemplos anteriores que es un commit:

cat el_commit_inicial

adc8bd279064ef2bc91057e5edf0996537e69edf...

De todas maneras, si revisamos el hash al que apunta podemos ver la metadata y confirmamos que es el commit "Added readme. Initial commit":

cat-file -p adc8bd279064ef2bc91057e5edf0996537e69edf6

tree 9fd51eba3...
author Manuel <manuel@meltstudio.co> 1592 -0500
commiter Manuel <manuel@meltstudio.co> 1592 -0500

Added readme. Initial commit

Por otro lado, en el segundo tag vemos que apunta también a un hash, pero en este caso no es un commit:

cat v1.0

ef9fdcae2b92887087e513f12b83e303f2d0f983

Revisemos el tipo:

cat-file -t ef9fdcae2b92887087e513f12b83e303f2d0f983

tag
//Es un objeto tipo tag.

Y ¿qué tiene adentro?

cat-file -p ef9fdcae2b92887087e513f12b83e303f2d0f983

object c5a401b9fc5d8022c6444e1c78c180dd6c...
type commit
tag v1.0
tagger Manuel <manuel@meltstudio.co> 1592 -0500

Version 1.0

Cuando hacemos una etiqueta anotativa, estamos creando un objeto tipo tag donde se guarda el mensaje (en este caso: "Version 1.0"), también se guarda a qué se le hizo el tag, es decir, a un commit (type commit), y adentro del tag encontramos el hash del commit.


En el siguiente video realizamos el ejemplo anterior y te explicamos cuáles son las diferencias:

Si existe algún error en el reproductor, puedes ver el video en el siguiente LINK.



Las refs y los objetos remotos

Es muy usual o casi obligatorio que un repositorio de Git tenga su versión remota, esto por la facilidad que tiene un equipo de sincornizar los cambios e ir trabajando conjuntamente.

Si existe algún error en el reproductor, puedes ver el video en el siguiente LINK.


Esta referencia se guarda en el árbol de .git/refs, y se almacena con el último valor para cada rama. Por ejemplo, cuando se añade un sitio remoto, usualmente con el nombre "origin" y lo que llega a él son los cambios de tu rama master.


Primeto haces push, y si te das cuenta, por defecto "origin" siempre está presente en tus push:

git remote add origin git@github.com:<user>/<repository.git>
git push origin master

Counting objects: 3, done
Compressing objects: 100% (2/2), done
Writing objects: 100% (7/7), 716 bytes, done
Total 7 (delta 2), reused 4 (delta 1)
To git@github.com:schacon/simplegit-progit.git
  a11bef0..ca82a6d  master -> master

Revisemos la carpeta .git/

tree .git/

.git 
└── refs 
|   └─ heads
|   |   └─ melt
|   └─ tags
|   |   └─ el_commit_inicial
|   |   └─ v1.0
|   └─ remotes
|   |   └─ origin
|   |   |   └─ master
...

Las referencias a sitios remotos son distintas de las ramas normales, primero porque no se ubican en la misma carpeta (como vimos antes, las ramas están en refs/heads), y segundo porque sólo son de lectura, esto significa que puedes hacer checkout sin que HEAD apunte a ella así que no se podrá actualizar.


Entonces, ¿Cómo funcionan push y merge?

En el siguiente video, te mostramos en detalle:


Si existe algún error en el reproductor, puedes ver el video en el siguiente LINK.


Lo verdaderamente interesante de todo este proceso es comprender Git inteligentemente, si existe un problema, algún reset o revert que no debió suceder, algún archivo perdido, etc... en cualquier momento puedes hacer uso del conocimiento en los hash de los objetos de Git para solucionarlo.


Esperamos que esta serie te haya gustado!

_________________________________________________________________________________________


¡Gracias por leer!


📍 Conéctate con nosotros en instagram👇


22 views

Join our newsletter to receive information about latest technologies trends and job offers

Thanks for subscribing!