Esta entrada es la segunda de la serie "Introducción a Git y el control de versiones" escrita para explicar que es Git y como se puede utilizar en equipos de trabajo. Entrada en la que se analizaran algunos comandos avanzados de Git. Centrándose en aquellos que permiten trabajar de forma eficaz con repositorios remotos, ramas y la gestión de versiones en equipo.
La serie de publicaciones consta de las siguientes entradas:
- Introducción a Git y el control de versiones
- Comandos avanzados de Git y su aplicación
- Mejores prácticas en Git
- Introducción a la metodología GitFlow
La publicación comienza con un análisis de los comandos avanzados de Git necesarios para clonar y trabajar con repositorios remotos, continuando con una revisión de los pasos para la gestión de ramas, para luego revisar herramientas avanzadas como git rebase
, git cherry-pick
, git stash
, y git reflog
. Esta entrada permite comprender y utilizar estos comandos para mejorar el control y la organización en los proyectos gestionados con Git.
Clonar y trabajar con repositorios remotos
Uno de los primeros comandos avanzados de Git que es necesario conocer de Git es git clone
. Este comando permite copiar un repositorio Git que se encuentra en un servidor remoto (como GitHub, GitLab o Bitbucket) a la máquina local.
Cuando se clona un repositorio, Git descarga todos los archivos, historial de commits y ramas desde el repositorio remoto y los guarda en una carpeta local. Siendo especialmente útil cuando un desarrollador se une a un proyecto ya existente o si se desea colaborar en un repositorio de código abierto.
Sintaxis y uso básico de git clone
La sintaxis básica de git clone
es:
git clone <URL del repositorio>
Por ejemplo, si se desea clonar un repositorio de GitHub llamado mi-proyecto
con la siguiente URL https://github.com/usuario/mi-proyecto.git
, se debe ejecutar el siguiente comando:
git clone https://github.com/usuario/mi-proyecto.git
Esto creará una carpeta llamada mi-proyecto
en la ruta donde se ejecute el comando que contendrá todos los archivos del repositorio.
Personalización del proceso de clonado
Si se desea que la carpeta local tenga un nombre diferente, este se conseguir proporcionando un segundo argumento al comando git clone
. Por ejemplo:
git clone https://github.com/usuario/mi-proyecto.git nuevo-nombre
Esto creará una carpeta llamada nuevo-nombre
en lugar de mi-proyecto
.
Trabajar con un repositorio clonado
Una vez clonado el repositorio, ya se puede comenzar a trabajar con él como se haría con cualquier otro proyecto. Todos los cambios que se hagan en la copia local podrán ser confirmados (usando commit
) y luego enviados al repositorio remoto mediante git push
. Los pasos para ello serían:
- Implementar cambios en los archivos.
- Agregar los cambios a la staging área con
git add
. - Confirmar los cambios con
git commit
. - Envías los cambios al repositorio remoto con
git push
.
Este es el flujo de trabajo habitual cuando se colabora en proyectos con otros desarrolladores.
Ramas (branches)
Una rama en Git es una línea paralela de desarrollo. Permite crear una copia del estado actual del proyecto y hacer cambios sin afectar la rama principal (generalmente llamada main
o master
). Esto es especialmente útil cuando se trabaja en una nueva característica o una corrección de errores, ya que, para evitar que la rama principal pueda dejar de funcionar durante los cambios, se puede desarrollar en una rama aislada y luego fusionar esos cambios una vez que estén listos.
Creación de ramas con git branch
y git checkout
En el caso de que se esté trabajando en una nueva característica llamada "mejoras en el modelo". Se puede crear una rama llamada model-improvements
usando el siguiente comando:
git branch model-improvements
Al ejecutar el comando, Git creará una nueva rama, pero se continúa estando en la rama actual. Para cambiar a la nueva rama se debe usar el comando git checkout
como se muestra a continuación:
git checkout model-improvements
Alternativamente, se pueden combinar ambos pasos con el parámetro -b
:
git checkout -b model-improvements
Este comando creará y se moverá a la nueva rama en un solo paso.
Visualización de ramas
Se pueden ver todas las ramas disponibles en un repositorio usando el siguiente comando:
git branch
Este comando lista las ramas locales. La rama en la que se estás actualmente estará marcada con un asterisco.
Fusión de ramas con git merge
Una vez terminado el trabajo en una rama, se deberían fusionar los cambios en la rama principal ( main
o master
). Para hacer esto, primero es necesario comprobar que se está en la rama en la que se desea fusionar los cambios (por ejemplo, main
):
git checkout main
Luego, se debe ejecutar el comando de fusión:
git merge model-improvements
Este comando combinará los cambios de la rama footer-improvements
en la rama main
.
Resolución de conflictos al fusionar ramas
Algunas veces, cuando se intentan fusionar dos ramas, Git no puede hacer la fusión automáticamente porque algunos archivos fueron modificados en ambas ramas de manera incompatible. Esto se conoce como un conflicto.
Cuando ocurre un conflicto, Git marca las áreas del código que están en conflicto para que el programador los resuelva manualmente. En esto casos se tendrá algo como lo siguiente en los archivos afectados:
<<<<<< HEAD Contenido en la rama actual ======= Contenido en la rama que se está fusionando >>>>>> model-improvements
El programador deberá editar el archivo para resolver el conflicto y luego confirmar los cambios:
git add archivo-afectado git commit
Git marca el conflicto como resuelto una vez que se confirmen los cambios.
Rebasing y cherry-picking
Además de git merge
existen otras opciones para combinar los cambios de una rama a otra.
¿Qué es git rebase
?
El comando git rebase
es una alternativa a git merge
que reorganiza la secuencia de commits. Cuando se usa rebase
, Git toma los cambios de una rama y los "vuelve a aplicar" en la rama actual, como si se estuvieran aplicando esos cambios nuevamente, sobre el estado más reciente de la rama base.
Ejemplo de git rebase
En el caso de que se tenga dos ramas: main
y feature
. Si el objetivo es mover los commits de feature
a main
, se puede hacer de la siguiente manera:
git checkout feature git rebase main
Esto significa que los commits en la rama feature
serán reaplicados sobre los commits de main
, y la historia del proyecto parecerá más lineal, sin tener la fusión típica que genera un merge
.
Rebase interactivo
El rebase interactivo ( git rebase -i
) es una herramienta que te permite modificar el historial de commits antes de aplicarlos. Pudiendo combinar, reordenar, o eliminar commits. Esto es útil para limpiar el historial antes de fusionar una rama.
Para iniciar un rebase interactivo se debe usar el comando:
git rebase -i <commit-hash>
El commit-hash
es el identificador del commit anterior al primero que se desea modificar. Git abrirá un editor donde se podrá decidir qué hacer con cada uno de los commits.
¿Qué es git cherry-pick
?
A veces, no es necesario fusionar una rama completa, sino solo un commit específico de otra rama. Aquí es donde entra en juego el comando git cherry-pick
.
Este comando toma un commit de otra rama y lo aplica a la rama actual, como si se hubiera hecho ese commit directamente en la rama donde se aplica.
Ejemplo de git cherry-pick
Si se tiene un commit en la rama feature
que se desea aplicar en main
. En primer lugar, se debe obtener el hash del commit con git log
, una vez hecho esto se puede mover a la rama de destino y aplicar el git cherry-pick
:
git checkout main git cherry-pick <commit-hash>
Este comando aplicará solo el commit seleccionado de feature
, al que corresponde el hash <commit-hash>
, a la rama main
.
Git Stash
git stash
es una herramienta útil cuando se está en medio de cambios no confirmados, pero es necesario cambiar de contexto sin perder el trabajo. En lugar de confirmar los cambios a medio hacer, se pueden "guardar" esos cambios temporalmente y volver a ellos más tarde.
Cómo usar git stash
Supongamos que se está trabajando en la rama main
y se han realizado cambios en varios archivos, pero no se desea confirmarlos todavía. Para guardar esos cambios sin perderlos se debe ejecutar:
git stash
Esto moverá los cambios actuales a un "stash" temporal y restaurará el directorio de trabajo al último commit. Ahora se puede cambiar de rama o realizar otras tareas sin preocuparte por perder los cambios.
Restaurar los cambios guardados
Cuando se esté listo para continuar trabajando en esos cambios, se pueden restaurar mediante el comando:
git stash apply
Esto volverá a aplicar los cambios que se guardaron anteriormente. Si deseas eliminar el stash después de aplicarlo, se puede usar:
git stash drop
Casos de uso de git stash
El comando git stash
es especialmente útil en varias situaciones, por ejemplo:
-
Interrupciones inesperadas: Si se está trabajando en una nueva característica, pero se presenta un problema urgente que es necesario resolver en otra rama, se puede hacer
stash
de los cambios, cambiar a la rama necesaria, resolver el problema y luego restaurar el trabajo. -
Experimentos temporales: Si se desea probar algo sin hacer commits, se puede usar
git stash
para limpiar el directorio de trabajo y volver a un estado limpio de forma rápida.
Reflog y recuperación de commits perdidos
git reflog
es una herramienta que permite ver el historial de todas las referencias de Git en un repositorio, incluyendo las operaciones que normalmente no se registran en git log
. Esto es útil cuando es necesario recuperar commits que podrían haberse perdido por un reset o un rebase.
Ejemplo de uso de git reflog
Si accidentalmente se ha aplicado un git reset --hard
y se han perdido algunos commits, es posible usar git reflog
para ver el historial de todas las operaciones recientes:
git reflog
Esto mostrará una lista de las acciones recientes en el repositorio, incluyendo los commits que se han perdido. Posteriormente, se puede recuperar un commit específico haciendo:
git checkout <commit-hash>
De esta manera, se puede restaurar el commit perdido y evitar tener que volver a realizar el trabajo.
Conclusiones
Los comandos avanzados de Git que se han visto en esta entrada como git rebase
, git cherry-pick
, git stash
, y git reflog
permiten gestionar de manera eficiente el historial de cambios y abordar situaciones complejas durante el proceso de desarrollo. Haciendo que Git sea una herramienta más flexible y adaptable. Cada uno de los comandos vistos tiene su funcionalidad durante el flujo de trabajo de un desarrollador, ayudando a mantener el código organizado y mejorando la colaboración dentro de los equipos. Con estos conocimientos avanzados, se está más preparado para enfrentarse a cualquier desafío que se presente en los flujos de trabajo con Git.
En la siguiente entrada de esta serie se explicarán las mejores prácticas para trabajar con Git.
Nota: La imagen de este artículo fue generada utilizando un modelo de inteligencia artificial.