Tu multiverso con Git

20-08-2025

Por Adrián Ferrera González

Git es una herramienta utilizada para la gestión de versiones de ficheros. Nos permite tener un control de versiones local. que opcionalmente podremos llevarlo a un sistema remoto.

Git fue pensado y siempre se ha explicado, haciendo la analogía con un árbol, sin embargo, a día de hoy, con la idea del multiverso muy presente podemos darle un enfoque más refrescante para las personas que se incorporan al mundo del desarrollo.

La sagrada línea temporal y los eventos canónicos

Iniciemos con el concepto de repositorio. Cuando hablamos de multiverso, hablamos de un conjunto de variaciones del mismo universo. El repositorio es el concepto que se encarga de englobar todas estas variantes (ramificaciones) y eventos canónicos (commits) en un mismo lugar y que nos permite trabajar con todas ellas.

Para indicar que queremos convertir un directorio en un repositorio Git, debemos ejecutar el comando:

git init

Esto creará un directorio .git en el que se almacenará toda la información relativa al control de versiones.

Git funciona como una línea de tiempo en la cual podemos registrar cambios en los ficheros, como si de eventos canónicos se tratara, de nuestros directorios en un punto de tiempo determinado, al cual se le conoce como "commit".

tu-multiverso-con-git-commit-1

Los sucesos ocurridos en esa línea del tiempo, no se almacenan en su totalidad para cada commit, sino que se añade información de forma incremental en base al commit anterior.

Es decir, sin la información previa, un evento en la línea de tiempo carecería de la información necesaria para poder ser reconstruido.

tu-multiverso-con-git-commit-2

Para observar el estado de nuestra línea de tiempo podemos utilizar el comando:

git log

Cada vez que queramos indicar que los cambios que creamos deben ser contemplados en el stage debemos añadirlos con:

git add [nombre de el/los ficheros]

O, como alternativa, podemos indicarle que añada todo lo que se encuentra en el directorio en el que nos encontramos:

git add .

Para visualizar el estado de nuestro stage podemos utilizar el comando:

git status

Una vez tenemos los cambios en nuestro stage, podemos decidir crear dicho "evento canónico" o "commit":

git commit -m "[el mensaje descriptivo que decidamos]"

También podemos unificar el comando de add y commit en uno solo de la siguiente forma:

git commit -a -m "[el mensaje descriptivo que decidamos]"

💡 Como habrás podido comprobar, es bastante incómodo tener que añadir a mano todos los ficheros, pero git add . añade todo. Existe un fichero llamado .gitignore ubicado en la raíz del repositorio, en el cual podemos indicar todos los directorios y ficheros que queramos ignorar. Por ejemplo: directorios de build, dependencias instaladas, ficheros con variables de entorno o secrets...

💡 Existen convenciones para la creación de estos commits, como puede ser gitmoji, Conventional Commits

Las ramificaciones temporales

Como en cualquier viaje en el tiempo que da pie a un multiverso, pueden ocurrir alteraciones de la línea temporal por las que se creen ramificaciones que sigan su propio camino con respecto a la original.

tu-multiverso-con-git-branch

En Git, además de la línea temporal principal (a menudo llamada main o master), podemos crear ramificaciones temporales o paralelas, conocidas como ramas. Las ramas nos permiten experimentar con nuevas funcionalidades, corregir errores o desarrollar nuevas características sin afectar la línea temporal principal.

Git checkout -b

Cuando queremos crear una nueva rama y movernos a ella, utilizamos el siguiente comando:

git checkout -b [nombre-de-la-rama]

Este comando crea una nueva rama y automáticamente nos posiciona en ella. Desde este punto, cualquier commit que hagamos se registrará en esta nueva rama, manteniendo la main intacta.

Git checkout

Una vez que hemos terminado de trabajar en una rama y queremos regresar a otra (por ejemplo, la rama main), utilizamos:

git checkout main

Este comando nos mueve a la rama main, donde podemos continuar trabajando o combinar las ramas que hemos creado. Es importante notar que siempre debemos asegurarnos de que todos nuestros cambios estén guardados antes de cambiar de rama, ya que, de lo contrario, Git nos pedirá que resolvamos los cambios pendientes.


Una parte importante es que estas ramas pueden volver a integrarse en "La Sagrada Línea Temporal" o incluso entre ellas, aunque esto último no suele ser un hábito muy recomendado.

tu-multiverso-con-git-merge

Ahora bien, la única forma que tenemos para poder unir dos líneas temporales es que estas sean congruentes entre sí y no creen conflictos. En caso de que esto suceda, deberemos ser nosotros quienes decidamos cuál debe ser el estado resultante.

tu-multiverso-con-git-merge-conflict

Git merge (ramas sobre ramas)

Para integrar los cambios de una rama en otra, utilizamos el comando git merge. Supongamos que estamos en la rama main y queremos incorporar los cambios de una rama llamada feature:

git merge feature

Esto combinará los cambios de la rama feature en main. Git intentará automáticamente fusionar los cambios, pero si ambos modificaron las mismas líneas de un archivo, se producirá un conflicto que deberá resolverse manualmente.

Resolución de conflictos

Cuando ocurre un conflicto, Git marca las áreas de conflicto en los archivos afectados. Debes editar estos archivos para resolver el conflicto y luego continuar con el proceso de fusión:

git add [archivos-resueltos]
git commit

Esto completará la fusión, aplicando los cambios combinados.

Compartiendo la línea temporal

Git no solo nos permite gestionar nuestras versiones de manera local, sino que también nos permite compartir esta información y colaborar con otras personas. Para ello, utilizamos repositorios remotos. Un repositorio remoto es una copia de nuestro repositorio alojada en un servidor externo, al que todos los miembros de un equipo pueden acceder. Esto es útil para mantener la consistencia entre diferentes entornos de desarrollo, asegurando que todas las personas colaboradoras estén en la misma "línea temporal".

Puestos a considerar "La Sagrada línea temporal" esta debería ser la rama principal que se encuentra en remoto.

Git Remote

Para trabajar con un repositorio remoto, primero necesitamos decirle a Git cuál es ese repositorio remoto. Esto se hace usando el comando:

git remote add origin [URL del repositorio]

Este comando enlaza nuestro repositorio local con un repositorio remoto que, por convención, suele llamarse origin. La URL del repositorio es la dirección donde está alojado el proyecto (puede ser en GitHub, GitLab, Bitbucket, etc.).

Git Pull, Push

Una vez que tenemos configurado nuestro repositorio remoto, podemos sincronizar nuestros cambios. Cuando queremos enviar nuestras versiones locales al repositorio remoto, utilizamos el comando git push:

git push origin main

tu-multiverso-con-git-push

Esto envía los commits de nuestra rama local main al repositorio remoto origin. Pero si queremos obtener los últimos cambios desde el repositorio remoto y aplicarlos a nuestra línea temporal local, utilizamos el comando git pull:

git pull origin main

Este comando descarga los cambios desde el repositorio remoto y los integra en nuestra rama local.

tu-multiverso-con-git-pull

Finalmente, si en algún momento queremos ver los repositorios remotos configurados o cambiar alguno de ellos, podemos usar:

git remote -v

Este comando muestra las URLs de los repositorios remotos asociados con nuestro repositorio local.

tu-multiverso-con-git-remote

De la misma forma, al tratar de combinar la línea de tiempo remota con la local pueden ocurrir conflictos, que deberán solucionarse tal y como indicábamos anteriormente.

Git Fetch

Antes de adentrarnos en los detalles de sincronización y fusión de cambios, es fundamental entender cómo Git nos permite estar al tanto de los cambios en el repositorio remoto sin necesariamente integrarlos en nuestra línea temporal local de inmediato. Aquí es donde entra en juego el comando git fetch.

git fetch origin

Descarga los últimos commits, archivos y ramas desde el repositorio remoto origin, pero no los fusiona con nuestra rama actual. De este modo, podemos revisar las nuevas líneas temporales (los cambios en las ramas remotas) sin comprometer nuestro trabajo actual.

Manteniendo la sagrada línea temporal

Con el tiempo, querrás combinar los cambios de diferentes ramas para integrar todas las nuevas funcionalidades o correcciones en la línea temporal principal en un entorno remoto y colaborativo. Aquí es donde entran en juego las revisiones de código.

Concepto de PR o MR

En proyectos colaborativos, antes de fusionar ramas, es común realizar una revisión de código a través de una Pull Request (PR) o Merge Request (MR). Esto implica que otra persona del equipo revise los cambios propuestos antes de que sean integrados en la línea temporal principal. Este proceso asegura que el código cumple con los estándares del proyecto y reduce la posibilidad de introducir errores.


Mejorar la legibilidad de la sagrada línea temporal

Una parte muy importante de la gestión temporal no es solo poder acceder a cada punto de ella cuando sea necesario, sino también entender qué ha ocurrido. Por ello que en los últimos años se han establecido hábitos que intentan mejorar esta parte, independientemente de la cantidad de commits que se generen durante el desarrollo.

Para mantener una historia de commits limpia y legible, Git ofrece varias herramientas. Dos de las más útiles son squash y rebase.

Squash

tu-multiverso-con-git-squash

El comando squash permite combinar múltiples commits en uno solo. Esto es útil cuando hemos realizado muchos pequeños commits mientras desarrollábamos una funcionalidad, y ahora queremos que todo ese trabajo aparezca como un único commit en la línea temporal.

git rebase -i [commit-antecesor]

Usando el rebase interactivo (-i), puedes seleccionar los commits que deseas "aplastar" (squash) y combinarlos en un solo commit.

Rebase

tu-multiverso-con-git-rebase

El comando rebase es otra herramienta poderosa que permite reorganizar o reescribir el historial de commits de una rama. En lugar de simplemente fusionar ramas, rebase re-aplica los cambios de una rama sobre otra, creando una historia lineal y más limpia:

git rebase [rama-destino]

Este comando toma todos los commits de la rama actual y los aplica sobre la rama-destino, eliminando bifurcaciones en la línea temporal.

Por ejemplo, si has estado trabajando en una rama feature y quieres traer los últimos cambios de main sin un merge tradicional, puedes hacer:

git rebase main

Al final de este proceso, los commits de feature aparecerán como si hubieran sido realizados después de los commits más recientes en main, lo que hace que la historia sea más lineal y fácil de seguir.

Cuando realicemos estas acciones, podría darse el caso de que no seamos capaces de subirlos a la rama remota, debido a que existe una incongruencia en cuanto a los commits existentes. Es por ello que debemos "forzar" la subida de código.

git push --force

Esto último debemos hacerlo con mucho cuidado y solo cuando nos aseguremos de que en nuestro local tenemos todos los cambios introducidos en la rama remota. Es decir, que ninguna persona haya subido código mientras estábamos trabajando en el entorno local.

Otra forma de hacerlo es utilizando --force-with-lease que hace lo mismo que --force pero se asegura que no hay cambios en la rama remota.

git push --force-with-lease

Una buena forma de garantizar esto y solucionar los conflictos que puedan existir previo a mezclar el código es utilizar el siguiente comando:

git pull origin main --rebase

Este comando realiza un rebase de nuestros cambios locales sobre los cambios más recientes del repositorio remoto. Es decir, en lugar de crear un commit de fusión (merge commit), Git aplica nuestros commits locales "por encima" de los commits que han sido añadidos al repositorio remoto. Esto permite mantener una historia de commits lineal, eliminando bifurcaciones y haciendo que la línea temporal sea más fácil de seguir.

El uso de --rebase es especialmente útil en equipos grandes, donde la historia del proyecto puede volverse rápidamente compleja debido a múltiples ramas y fusiones. Al usar rebase, facilitamos la navegación por el historial de commits y hacemos que la integración continua sea más sencilla y limpia.