La guía de Git que nunca tuve
- Andrés Cruz
Antes de empezar a mostrar algunos comandos muy útiles para empezar a trabjar con Git, vamos a entrar en contexto y explicar que es Git.
¿Qué es Git?
Git es un sistema de control de versiones de código abierto bajo licencia GPLv2 y que podemos emplear libremente. Fue diseñado por el mismo creador de Linux Linus Torvald que nos permite almacenar, cambiar y colaborar código con otros usuarios, es decir, empleando Git, podemos tener un completo control sobre el código.
Como descargo de responsabilidad, me gustaría señalar que Git es un tema enorme. Se han escrito libros sobre Git y publicaciones de blogs que también podrían confundirse con artículos académicos. Eso no es lo que busco aquí. No soy un experto en Git. Mi objetivo aquí es escribir la publicación sobre los fundamentos de Git que desearía haber tenido al aprender Git.
Como desarrolladores, nuestra rutina diaria gira en torno a leer, escribir y revisar código. Podría decirse que Git es una de las herramientas más importantes que utilizamos. Dominar las características y funcionalidades que ofrece Git es una de las mejores inversiones que puedes hacer en ti mismo como desarrollador.
Fundamentos
Los fundamentos de git son los repositorios, que no es más que una carpeta o caja en donde está nuestro código y mediante Git es el que mantiene un control sobre nuestros archivos en base a algunos lineamientos que son los siguientes:
- Modificado (modified):
- Representa archivos que han sufrido cambios en el directorio de trabajo, pero aún no se han marcado para ser confirmados.
- Estos cambios no se han registrado en el repositorio.
- Preparado (staged):
- Se refiere a los archivos que han sido modificados en el directorio de trabajo y se han marcado como listos para ser confirmados en el repositorio local.
- Estos archivos se encuentran en un área temporal transitoria antes de ser confirmados definitivamente.
- La acción de marcar archivos como preparados se llama “add” (esto es un comando que veremos más adelante).
- Confirmado (committed):
- Indica que el archivo se ha grabado en el repositorio local.
- La acción de confirmar los cambios se llama “commit”.
- Una vez confirmado, el archivo forma parte del historial de versiones del repositorio.
Estos 3 estados son claves y forman parte del ciclo de vida de los archivos en un repositorio.
Estos no son más que estados en los cuales pueden estar nuestros archivos cuando usamos git en un proyecto.
Branches
Una rama en Git es simplemente un apuntador que señala un estado de nuestra aplicación en un repositorio que señala una confirmación específica dentro del historial de versiones, podemos navegar mediante este apuntador para ver estados anteriores o para movernos a nuevos estados en pase a las confirmaciones que hagamos en nuestro proyecto mediante git.
En un repositorio de Git, encontrará una línea principal de desarrollo, normalmente denominada "main" o "master" (obsoleta) de la que divergen varias ramas. Estas ramas representan flujos de trabajo simultáneos, lo que permite a los desarrolladores abordar múltiples funciones o correcciones simultáneamente dentro del mismo proyecto.
Commits
Los comits de Git sirven como paquetes de código actualizado, capturando una instantánea del código del proyecto en un momento específico. Cada commit registra los cambios realizados desde que se registró la última confirmación, y en conjunto crean un historial completo del recorrido de desarrollo del proyecto.
Al hacer referencia a los commits, generalmente utilizará su hash criptográfico identificado de forma única.
git show abc123def456789
Tags
Las etiquetas de Git sirven como puntos de referencia dentro de la historia de Git y, por lo general, marcan hitos importantes en el desarrollo de un proyecto, como lanzamientos, versiones o confirmaciones destacadas. Estas etiquetas son invaluables para marcar puntos específicos en el tiempo y a menudo representan los puntos de partida o los principales logros en el recorrido de un proyecto.
HEAD
El HEAD indica la confirmación más reciente en la rama actualmente desprotegida, y sirve como puntero a cualquier referencia dentro del repositorio. Cuando estás en una rama específica, HEAD apunta a la última confirmación en esa rama. A veces, en lugar de apuntar a la punta de una rama, HEAD puede apuntar directamente a una confirmación específica (estado HEAD separado).
En Git, HEAD es un puntero que hace referencia al punto actual en el historial de cambios del repositorio con el que estás trabajando. Por lo general, apunta al último commit en la rama en la que te encuentras actualmente. Sin embargo, como también puedes moverte entre commits, hay casos en los que HEAD no necesariamente apunta al último commit.
¿Y por qué se llama HEAD? Bueno, cada cambio registrado en el repositorio se identifica mediante un hash único (del que hablaremos más adelante). Referirse a un commit específico por su hash sería bastante incómodo.
Imagina lo siguiente: tienes la habilidad de viajar en el tiempo y el espacio. En ese escenario, HEAD siempre apuntaría a tu ubicación actual, sin importar cuándo ni dónde te encuentres.
Stages
Comprender el Git stage es crucial para navegar por su flujo de trabajo de Git. Representan las transiciones lógicas donde ocurren los cambios en sus archivos antes de que se envíen al repositorio. Profundicemos en el concepto de etapas de Git:
Directorio de trabajo/Working directory
El directorio de trabajo es donde edita, modifica y crea archivos para su proyecto. Representa el estado actual de sus archivos en su máquina local.
Staging area
El área de Staging area es como un área de espera o una zona de confirmación previa donde prepara sus cambios antes de enviarlos al repositorio.
Comando útil aquí: git add También se puede usar git rm para cancelar los cambios.
Local repository
El repositorio local es donde Git almacena permanentemente los cambios confirmados. Le permite revisar el historial de su proyecto, volver a estados anteriores y colaborar con otros en la misma base de código.
You can commit changes that are ready in the staging area with: git commit
Como saber si tienes git instalado:
Muchos sistemas ya traer instalado por defecto git ya listo para emplear, aunque, es probable que sea una versión antigua así que pudieras actualizarlo, de igual manera, para determinar si tenemos git instalado, podemos ejecutar un comando:
git --version
Repositorio remoto/Remote repository
El repositorio remoto es una ubicación centralizada, normalmente alojada en un servidor (como GitHub, GitLab o Bitbucket), donde puedes compartir y colaborar con otros en tu proyecto.
Puede usar comandos como git push y git pull para enviar/extraer los cambios confirmados desde su repositorio local al repositorio remoto.
Empezando con Git
Bueno, tienes que empezar por algún lado, y en Git ese es tu espacio de trabajo. Puede bifurcar o clonar un repositorio existente y tener una copia de ese espacio de trabajo, o si está comenzando completamente desde cero en una nueva carpeta local en su máquina, debe convertirlo en un repositorio git con:
git init
El siguiente paso, que no debe pasarse por alto, es configurar sus credenciales.
Configurar credenciales
Cuando ejecute push y pull a un repositorio remoto, no querrá tener que escribir su nombre de usuario y contraseña cada vez; evítelo simplemente ejecutando el siguiente comando:
git config --global credential.helper store
La primera vez que interactúes con el repositorio remoto, Git te pedirá que ingreses tu nombre de usuario y contraseña. Y después de eso, no se te volverá a preguntar.
Es importante tener en cuenta que las credenciales se almacenan en formato de texto sin formato dentro de un archivo .git-credentials.
Para verificar las credenciales configuradas, puede usar el siguiente comando:
git config --global credential.helper
Trabajar con branches/ramas
Cuando se trabaja localmente, es fundamental saber en qué sucursal se encuentra actualmente. Estos comandos son útiles:
# Will show the changes in the local repository
git branch
# Or create a branch directly with
git branch feature-branch-name
Para realizar la transición entre ramas utilice:
git switch
Además de la transición entre ellos, también puede usar:
git checkout
# A shortcut to switch to a branch that is yet to be created with the -b flag
git checkout -b feature-branch-name
Para verificar el estado del repositorio, use:
git status
Una excelente manera de tener siempre una vista clara de su rama actual es verla directamente en la terminal. Muchos complementos de terminal pueden ayudar con esto. Acá hay uno.
Trabajar con commits
Cuando trabaje con commits, utilice git commit -m para registrar cambios, git amend para modificar la confirmación más reciente y haga todo lo posible para cumplir con las convenciones de mensajes de confirmación.
# Make sure to add a message to each commit
git commit -m "meaningful message"
Si tiene cambios en su último commit, no tiene que crear otra confirmación por completo; puede usar el indicador - - modificar para modificar la confirmación más reciente con sus cambios preparados.
# make your changes
git add .
git commit --amend
# This will open your default text editor to modify the commit message if needed.
git push origin your_branch --force
Tenga cuidado al utilizar --force, ya que tiene el potencial de sobrescribir el historial de la rama de destino. En general, se debe evitar su aplicación en la rama principal/master.
Como regla general, es mejor comprometerse con mayor frecuencia para evitar perder el progreso o restablecer accidentalmente los cambios no realizados. Se puede reescribir el historial posteriormente aplastando múltiples commits o realizando una rebase interactiva.
Utilice git log para mostrar una lista cronológica de confirmaciones, comenzando desde la confirmación más reciente y retrocediendo en el tiempo.
Manipular el historial
Manipular la historia implica algunos comandos poderosos. Rebase reescribe el historial de confirmaciones, Squashing combina varias confirmaciones en una y Cherry-picking selecciona confirmaciones específicas.
¿Cómo puedo deshacer mis cambios?
Es posible deshacer el último commit si el mismo todavía no ha sido publicado en el respositorio, bastante últil por si te haz equivocado al definir el mismo, para ello:
git reset --soft HEAD~1
El parámetro reset permite retroceder a otra revisión, en este caso, el apuntado por HEAD menos uno, recordemos que HEAD apunta al estado actual por lo tanto, si le restamos 1 apuntaría al anterior.
Finalmente, el parámetro --soft es el que va a hacer que los cambios configurados en el commit se mantengan en el repositorio sin eliminarlos. Si no quieres mantener los cambios, coloca la opción de --hard en su lugar:
git reset --hard HEAD~1
Rebasing y merging
Tiene sentido comparar el rebase con la fusión, ya que su objetivo es el mismo pero lo logran de diferentes maneras. La diferencia crucial es que el rebase reescribe la historia del proyecto. Una opción deseada para proyectos que valoran un historial de proyecto claro y fácilmente comprensible. Por otro lado, la fusión mantiene los historiales de ambas ramas generando una nueva confirmación de fusión.
Durante una rebase, el historial de confirmación de la rama de características se reestructura a medida que se mueve al HEAD de la rama principal.
El flujo de trabajo aquí es bastante sencillo.
Asegúrese de estar en la rama que desea cambiar y obtenga los últimos cambios del repositorio remoto:
git checkout your_branch
git fetch
Ahora elija la rama en la que desea rebase y ejecute este comando:
git rebase upstream_branch
Después de cambiar la base, es posible que necesites forzar la publicación de los cambios si la rama ya se envió a un repositorio remoto:
git push origin your_branch --force
Squashing
Git squashing se utiliza para condensar múltiples confirmaciones en una única confirmación cohesiva.
El concepto es fácil de entender y especialmente útil si el método de unificación de código que se utiliza es el rebase, ya que el historial se alterará, es importante tener en cuenta los efectos en el historial del proyecto. Ha habido ocasiones en las que he tenido dificultades para realizar un squash, especialmente usando el rebase interactivo, afortunadamente tenemos algunas herramientas que nos pueden ayudar. Este es mi método preferido de aplastamiento, que implica mover el puntero HEAD hacia atrás X número de confirmaciones mientras se mantienen los cambios preparados.
# Change to the number after HEAD~ depending on the commits you want to squash
git reset --soft HEAD~X
git commit -m "Your squashed commit message"
git push origin your_branch --force
Cherry-picking
La selección selectiva es útil para incorporar selectivamente cambios de una rama a otra, especialmente cuando fusionar ramas enteras no es deseable o factible. Sin embargo, es importante utilizar la selección con prudencia, ya que puede generar confirmaciones duplicadas e historiales divergentes si se aplica incorrectamente.
Para realizar esto, primero debe identificar el hash de confirmación de la confirmación que desea seleccionar; puede hacerlo con git log. Una vez que haya identificado el hash de confirmación, puede ejecutar:
git checkout target_branch
git cherry-pick <commit-hash> # Do this multiple times if multiple commits are wanted
git push origin target_branch
Comandos avanzados de Git
Signing commits
Firmar commits es una forma de verificar la autenticidad e integridad de sus confirmaciones en Git. Le permite firmar criptográficamente sus confirmaciones utilizando su clave GPG (GNU Privacy Guard), asegurando a Git que usted es efectivamente el autor de la confirmación. Puede hacerlo creando una clave GPG y configurando Git para usar la clave al realizar la confirmación. Aquí están los pasos:
# Generate a GPG key
gpg --gen-key
# Configure Git to Use Your GPG Key
git config --global user.signingkey <your-gpg-key-id>
# Add the public key to your GitHub account
# Signing your commits with the -S flag
git commit -S -m "Your commit message"
# View signed commits
git log --show-signature
Git reflog
Un tema que no hemos explorado son las referencias de Git, son punteros a varios objetos dentro del repositorio, principalmente confirmaciones, pero también etiquetas y ramas. Sirven como puntos con nombre en el historial de Git, lo que permite a los usuarios navegar a través de la línea de tiempo del repositorio y acceder a instantáneas específicas del proyecto. Saber cómo navegar por las referencias de git puede ser muy útil y pueden usar git reflog para hacer precisamente eso. Éstos son algunos de los beneficios:
- Recuperar confirmaciones o ramas perdidas
- Depuración y solución de problemas
- Deshacer errores
Interactive rebase
La rebase interactiva es una poderosa característica de Git que le permite reescribir el historial de confirmaciones de forma interactiva. Le permite modificar, reordenar, combinar o eliminar confirmaciones antes de aplicarlas a una rama.
Para poder utilizarlo es necesario familiarizarse con las posibles acciones tales como:
- Pick (“p“)
- Reword (“r“)
- Edit (“e“)
- Squash (“s“)
- Drop (“d“)
Conflicts
No entre en pánico, cuando intenta fusionar o cambiar la base de una rama y se detectan conflictos, solo significa que hay cambios conflictivos entre diferentes versiones del mismo archivo o archivos en su repositorio y se pueden resolver fácilmente (la mayoría de las veces).
Por lo general, se indican dentro de los archivos afectados, donde Git inserta marcadores de conflicto <<<<<<<, ======= y >>>>>>> para resaltar las secciones en conflicto. Decida qué cambios conservar, modificar o eliminar, asegurándose de que el código resultante tenga sentido y conserve la funcionalidad prevista.
Después de resolver manualmente los conflictos en los archivos en conflicto, elimine los marcadores de conflicto <<<<<<<, ======= y >>>>>>> y ajuste el código según sea necesario.
Guarde los cambios en los archivos en conflicto una vez que esté satisfecho con la resolución.
Hoja de trucos de Git
# Clone a Repository
git clone <repository_url>
# Stage Changes for Commit
git add <file(s)>
# Commit Changes
git commit -m "Commit message"
# Push Changes to the Remote Repository
git push
# Force Push Changes (use with caution)
git push --force
# Reset Working Directory to Last Commit
git reset --hard
# Create a New Branch
git branch <branch_name>
# Switch to a Different Branch
git checkout <branch_name>
# Merge Changes from Another Branch
git merge <branch_name>
# Rebase Changes onto Another Branch (use with caution)
git rebase <base_branch>
# View Status of Working Directory
git status
# View Commit History
git log
# Undo Last Commit (use with caution)
git reset --soft HEAD^
# Discard Changes in Working Directory
git restore <file(s)>
# Retrieve Lost Commit References
git reflog
# Interactive Rebase to Rearrange Commits
git rebase --interactive HEAD~3
Artículo original:
https://medium.com/@jake.page91/the-guide-to-git-i-never-had-a89048d4703a
Desarrollo con Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter