A lo largo de los años he observado que muchos programadores, sobre todo cuando están empezando con el control de código fuente, tienden a confundir ciertos conceptos sencillos de esta herramienta.
Dentro de ésta existen 3 conceptos que son clave, muy sencillos y no podemos confundir, así que vamos a darles un repaso rápido.
main
Como sabes, los sistemas de control de código fuente como Git trabajan con el concepto de ramas (o branches en inglés). Dicho de manera rápida y básica, una rama no es más que un nombre que se da a un commit, a partir del cual se empieza a trabajar de manera independiente y con el que se van a enlazar nuevos commits de esa misma rama. Las ramas pueden mezclarse de modo que todo el trabajo hecho en una de ellas pase a formar parte de otra.
Por si no lo tienes claro, un commit es un conjunto de cambios en los archivos que hemos dado por buenos y que queremos almacenar como una instantánea de cara al futuro. Los commits se relacionan unos con otros en una o varias secuencias para poder ir viendo la historia de un determinado archivo a lo largo del tiempo. Es el concepto central de todo sistema de control de código.
Existe una rama predeterminada que se crea automáticamente cuando se crea un repositorio que se llama rama main.
Actualización posterior: en realidad, hasta mediados del año 2020 esta rama se llamaba "master" y no "main". Pero por aquel entonces, aunque existen diversas teorías sobre el origen de ese nombre, se decidió que era una referencia al esclavismo ("master" de "amo", frente a "slave" de "esclavo. Otras teorías hablan, con más lógica IMHO, de que viene de "master copy" o copia maestra o principal) y que había que renombrarla. Así que ahora es "main" y no "master".
Por regla general a main se la considera la rama principal y la raíz de la mayoría de las demás ramas. Lo más habitual es que en main se encuentre el "código definitivo", que luego va a producción, y es la rama en la que se mezclan todas las demás tarde o temprano para dar por finalizada una tarea e incorporarla al producto final:
Esta manera de trabajar con ramas nos permite llevar en paralelo varios desarrollos relacionados sin importar que cada uno de ellos termine en momentos muy diferentes, ya que no interfieren, pudiendo mezclarlos todos al final.
Lo más habitual es que para poder mezclar otra rama cualquiera con main haya que pedir permiso y que alguien lo revise todo antes de permitirlo. Es lo que se denomina un "pull request". O simplemente que la rama main se encuentre protegida de modo que solo si se pasan todos los test y aseguramos que el producto funciona, sea posible mezclarse con ella. De este modo impedimos que cualquiera pueda llevar al producto final código que no cumple unos mínimos de calidad.
origin
Como seguramente sabrás Git es un sistema de control de código distribuido. Esto quiere decir que, aunque todos los desarrolladores tienen una copia exacta del mismo repositorio en su disco duro, existen uno o más repositorios remotos contra los que trabajamos, y que son los que almacenan el estado final del producto. Estos repositorios remotos se suelen llamar simplemente "remotos", y no todo el mundo tiene permiso para enviar commits hacia ellos (lo que se llama hacer un push).
Bien, pues origin es simplemente el nombre predeterminado que recibe el repositorio remoto principal contra el que trabajamos. Cuando clonamos un repositorio por primera vez desde GitHub o cualquier otro sistema remoto, el nombre que se le da a ese repositorio "maestro" es precisamente origin.
De todos modos ese nombre se puede cambiar, y se pueden crear más remotos contra los que hacer push. Pero en un porcentaje muy alto de los casos, como ese nombre por omisión no se cambia, puedes asumir que vas a enviar la información a origin.
HEAD
El concepto de HEAD
es muy simple: se refiere al commit en el que está tu repositorio posicionado en cada momento. Por regla general HEAD
suele coincidir con el último commit de la rama en la que estés, ya que habitualmente estás trabajando en lo último. Pero si te mueves hacia cualquier otro commit anterior entonces el HEAD estará más atrás.
De hecho, si tienes el repositorio actualizado (te has traído los últimos cambios de origin) y estás trabajando en la rama main lo más habitual es que coincidan las tres cosas.
Por ejemplo, este es el log, mostrando las ramas, del repositorio de un proyecto Open Source en el que participo. El HEAD
local se muestra como un punto con borde azul. Como se puede observar, en el momento en el que saqué la captura tenía en local la rama master (hoy en día sería main) y estaba ubicado en el último commit (cuyo hash identificador comienza por bdf09f20
) y coincide con el último commit en el origen:
Si por el contrario me muevo a otra rama o a un commit anterior, o si el repositorio de origen en la misma rama va por delante de lo que yo tengo en local, ninguno de los tres tiene por qué coincidir. Por ejemplo, me he movido a un commit anterior (el 6068a1c8
): y ahora mismo mi HEAD
local está 5 commits por detrás (es la que está en negrita con un punto de borde azul), mientras que la rama máster (que replica a la misma en el origen) está 5 commits por delante. El HEAD
del repositorio remoto (origen) está en el último commit:
En resumen
Aunque se trata de conceptos sencillos no siempre están claros para todo el mundo. De hecho, tanto main como origin son nombres sobre los que existe una convención en cuanto a su uso, pero no tienen por qué existir ya que la rama principal puede llamarse de otra manera cualquiera, y el origen principal también puede tener otro nombre (aunque estos dos sean los más habituales).
Sin embargo, HEAD
es un nombre constante y un concepto que no tiene discusión, refiriéndose siempre al commit en el que tenemos posicionado el repositorio en el momento actual. Independientemente de la rama en la que estemos, de cómo se llame la rama principal o el repositorio principal remoto.
Espero que te haya servido para aclarar estos 3 conceptos si no los tenías controlados del todo 😊