¿Que es el staging y los repositorios?

Para iniciar un repositorio, o sea, activar el sistema de control de versiones de Git en el proyecto, solo debes ejecutar el comando $ git init. Este comando se encargará de dos cosas: primero , crear una carpeta .git, donde se guardará todas la base de datos con cambios atómicos de nuestro proyecto; y segundo, creará un área conocida como Staging , que guardará temporalmente nuestros archivos cuando ejecutemos el comando add y nos permitirá, más adelante, guardar estos cambios en el repositorio con el comando commit.

Ciclo de vida o estados de los archivos en Git:

Cuando trabajamos con git nuestros archivos pueden vivir y moverse entre 4 estados diferentes (cuando trabajamos con repositorios remotos pueden ser más estados):

  • Archivos tracked: son los archivos que viven dentro de Git, no tienen cambios pendientes y sus últimas actualizaciones han sido guardadas en el repositorio gracias a los comandos git add y git commit.
  • Archivos Staged: son archivos en Staging. Viven dentro de GIt y son los que han sido añadidos por el comando git add, aunque no se han consolidado sus cambios. Git sabe de la existencia de estos cambios, pero no han sido guardados definitivamente en el repositorio porque falta ejecutar el comando commit.
  • Archivos Unstaged: son como archivos en tracked pero Unstaged. Son archivos que viven en Git pero no se les ha aplicado el comando git add ni el git commit. Git tiene un registro de estos archivos, pero no están actualizados, solo están guardadas sus últimas versiones en el disco duro.
  • Archivos Untracked: son archivos que no viven dentro de Git, sólo en el disco duro. No se les ha aplicado git add, así que Git no tiene registro de su existencia. Solo hay un caso muy raro donde los archivos tienen dos estados al mismo tiempo: staged y untracked. Esto pasa cuando guardas cambios con el comando git add, y antes de hacer el commit haces nuevos cambios que no estan en el Staging porque no has aplicado git add.

Comandos para mover archivos entre los estados de Git

  • $ git status: nos permite ver el estado de todos nuestros archivos y carpetas.
  • $ git add: nos ayuda a mover archivos del Untracked o Unstaged al estado Staged. Podemos usar $ git add nombre-del-archivo-o-carpetapara añadir archivos y carpetas individuales o $ git add -A para mover todos los archivos de nuestro proyecto ( tanto los Untracked como los Unstaged).
  • $ git reset HEAD: nos ayuda a traer archivos del estado Staged para devolverlos a su estado anterior. Si estaban los archivos en Unstaged, vuelven allí. Asi tambien como si estaban en Untracked.
  • $ git commit: nos ayuda a llevar archivos del estado Unstaged al estado Tracked.Este es el estado donde los archivos han sido guardados o actualizados en el repositorio. Git nos pedirá que dejemos un mensaje para recordar los cambios realizados y con el argumento -m escribirlo. (git commit -m).
  • $ git rm: este comando necesita alguno de los siguientes argumento para poder ejecutarse correctamente:
    • $ git rm --cached: Lleva los archivos que le indiquemos al estado Untracked.
    • $ git rm --force: Elimina los archivos de Git y del disco duro. Git guarda el registro de la existencia de los archivos, por lo que podremos recuperarlos si es necesario usando comandos más avanzados.

Volver en el tiempo en nuestro repositorio utilizando reset y checkout

El comando $ git checkout + ID del commit nos permite viajar en el tiempo. Podremos volver a cualquier versión anterior de un archivo específico o incluso del proyecto entero. Esta es la forma de crear ramas y movernos entre ellas. Usando el comando git reset volvemos en el tiempo y borramos los cambios que hicimos después de este commit. Git reset y git rm son comandos con utilidades muy diferentes, pero aún así se confunden muy fácilmente.

git rm

Este comando nos ayuda a eliminar archivos de Git sin eliminar su historial del sistema de versiones. Esto quiere decir que si necesitamos recuperar el archivo solo debemos "viajar en el tiempo" y recuperar el último commit antes de borrar el archivo en cuestión. Recuerda que git rm no puede usarse porque si. Debemos usar uno de los flags para indicarle a Git cómo eliminar los archivos que ya no necesitamos en la última versión del proyecto:

  • $ git rm --cached: Elimina los archivos de nuestro repositorio local y el área de staging, pero los mantiene en nuestro disco duro. Básicamente le dice a GIT que deje de trackear el historial de cambios de estos archivos, por lo que pasarán a un estado untracked.
  • $ git rm --force: Elimina los archivos de Git y del disco duro. Git siempre guarda todo, por lo que podemos acceder al registro de la existencia de los archivos, de modo que podremos recuperarlos si es necesario ( pero debemos usar comandos más avanzados).>

git reset

Este comando nos ayuda a volver en el tiempo. Pero no como git checkout que nos deja ir, mirar, pasear y volver. Con git reset volvemos al pasado sin la posibilidad de volver al futuro. Borramos la historia y la debemos sobreescribir. No hay vuelta a atrás. Este comando es muy peligroso y debemos usarlo solo en caso de emergencia. Recordar que debemos usar algunas de estas dos opciones:

  • $ git reset --soft: todo el historial y los registros de Git pero guardamos los cambios que tengamos en staging, así podemos aplicar las últimas actualizaciónes a un nuevo commit. Mantiene los archivos del área de staging para que podamos aplicar nuestros últimos cambios pero desde un commit anterior.
  • $ git reset --hard: Borra todo. Todo todito, absolutamente todo. Toda la información de los commit y del área de staging se borra del historial. Borra toda la información que tengamos en el área de staging ( y perdiendo todo para siempre)
  • $ git reset HEAD: este es el comando para sacar archivos del área de stagin. No para borrarlos ni nada de eso, solo para que los últimos cambios de estos archivos no se envíen al último commit, a menos que cambiemos de opinión y los incluyamos de nuevo en staging con git add, por supuesto.

¿Cuando usar git rm y git reset HEAD?

Bueno, todos los cambios están en el área de Staging, incluido el archivo con los cambios que no están listos. Esto significa que debemos sacar ese archivo del Staging para poder hacer commit de todos los demás.

Con $ git rm lo que haremos será eliminar este archivo completamente de git! Todavía tendremos el historial de cambios de este archivo, con la eliminacion del archivo como su última actualización. Recuerda que en este caso no buscábamos eliminar un archivo, solo dejarlo como estaba y actualizado después, no en este commit.

En cambio scon $ git reset HEAD, lo único que harémos será move estos cambios de Staging a Unstaged. Seguiremos teniendo los últimos cambios en el archivo, el repositorio mantendrá el archivo ( no con sus últimos cambios pero si con los últimos en los que hicimos commit) y no habremos perdido nada.

Introducción a las ramas o branches de Git

Las ramas son la forma de hacer cambios en nuestro proyecto sin afectar el flujo de trabajo de la rama principal. Esto es porque queremos trabajar una parte muy especifica de la aplicación o simplemente experimentar. La cabecera o HEAD representa la rama y el commit de esa rama donde estamos trabajando. Por defecto, esta cabecera aparecerá en el ultimo commit de nuestra rama principal. Pero podemos cambiarlo: $ git checkout -b rama o crear una rama: $ git branch rama o movernos en el tiempo a cualquier otro commit de cualquier otra rama con los comandos: $ git reset id-commit o $ git checkout rama-o-id-commit.

Cómo funcionan las llaves públicas y privadas

Las llaves publicas y privadas nos ayudan a cifrar y descifrar nuestros archivos de forma que los podamos compartir sin correr el riesgo de que sean interceptados por personas con malas intenciones.

La forma de hacerlo es la siguiente:
  1. Ambas personas deben crear su llave pública y privada.
  2. Ambas personas pueden compartir su llave pública a las otras partes.
  3. (recuerda que esta llave es pública, no hay problema si la "interceptan").
  4. La persona que quiera compartir un mensaje puede usar la llave pública de la otra persona para cifrar los archivos y asegurarse que solo puedan ser descifrados con la llave privada de la persona con la que queremos compartir el mensaje.
  5. El mensaje está cifrado y puede ser enviado a otra persona sin problemas en caso de que los archivos sean interceptados.
  6. La persona a la que enviamos el mensaje cifrado puede usar su llave privada para descrifrar el mensaje y ver los archivos.

Configurar las llaves ssh en local

  • 1er paso: generar tus llaves SSH. La llave privada puede ir protegida con una contraseña.

    ssh-keygen -t rsa -b 4096 -C "tu@email.com"

  • 2º paso : terminar de configurar nuestro sistema. En Windows:
    1. Encender el "servidor" de llaves SSH de tu computadora eval $(ssh-agent -s)
    2. Añadir tu llave SSH a este "servidor" ssh-add ruta-donde-guardaste-tu-llave-privada

Conexión a GitHub con SSH

Solo se crean una SSH por computadora.

Después de crear nuestras llaves SSH podemos entregarle la llave pública a gitHub para comunicarnos de forma segura y sin necesidad de escribir nuestro usuario y contraseña todo el tiempo.

Para esto entrarás a la COnfiguración de llaves SSH en GITHUB, crear una nueva llave con el nombre que le quieras dar y el contenido de la llave pública de tu computadora.

Ahora podemos actualizar la URL que guardamos en nuestro repositorio remoto, solo que en vez de guardar la URL con HTTPS, vamos a usar la URL con SSH:

$ git remote set-url origin url-ssh-del-repositorio-en-gitHub

Tags o etiquetas

Las tags o etiquetas nos permiten asignar versiones a los commits con los cambios más importantes o significativos de nuestro proyecto.

Comandos para trabajar con etiquetas:
  • Crear un nuevo tag y asignarlo a un commit:
    $ git tag -a nombre-del-tag id-del-commit
  • Borrar un tag en el repositorio local:
    $ git tag -d nombre-del-tag
  • Listar los tags de nuestro repositorio local:
    $ git tag

Flujo de trabajo básico con un repositorio remoto

Por ahora, nuestro proyecto vive únicamente en nuestra computadora. Esto significa que no hay forma de que otros miembros del equipo trabajen el él.

Para solucionar esto están los servidores remotos: un nuevo estado que deben seguir nuestros archivos para conectarse y trabajar con equipos de cualquier parte del mundo.

Estos servidores remotos pueden estar alojados en GITHUB, GITLAB, BitBucket, entre otros. Lo que van a hacer es guardar el mismo repositorio que tienes en tu computadora y darnos una URL con la que todos podremos acceder a los archivos del proyecto para descargarlos, hacer cambios y volverlos a enviar al servidor remoto para que otras personas vean los cambios, comparen sus versiones y creen nuevas propuestas para el proyecto.

Esto significa que debes aprendender algunos nuevos comandos:
  • $ git clone url_del_servidor_remoto: Nos permite descargar los archivos de la última versión de la rama principal y todo el historial de cambios en la carpeta .git.
  • $ git push: Luego de hacer git add y git commit debemos ejecutar este comando para mandar los cambios al servidor remoto.
  • $ git fetch: Lo usamos para traer actualizaciones del servidor remoto y guardarlas en nuestro repositorio local ( en caso de haberlas).
  • $ git merge: Tambien usamos el comando git merge con servidores remotos. Lo necesitamos para combinar los últimos cambios del servidor remoto y nuestro directorio de trabajo.
  • $ git pull: Básicamente, git fetch y git merge al mismo tiempo.

Flujo de trabajo profesional con pull request

En un entorno profesional normalmente se bloquea la rama master, y para enviar código a dicha rama pasa por un code review y si se aprueba se unen los códigos con los llamados merge request.

Para analizar pruebas enviamos el código a servidores que normalmente los llamamos staging develop(servidores de pruebas) al realizar las pruebas pertinenetes tanto del código como de la aplicación estos pasan al servidor de producción con el ya antes mencionado merge request.

git rebase: reorganizar el trabajo realizado

El comando rebase es una mala práctica, nunca se debe usar, pero para efectos del tutorial lo veremos para hacer tus propios experimentos. Con rebase puedes recoger todos los cambios confirmados en una rama y ponerlos sobre otra.

  • Cambiamos a la rama que queremos traer los cambios $ git checkout experiment
  • Aplicamos rebase para traer los cambios de la rama que queremos $ git rebase main

git stash: guardar cambios en memoria y recuperarlos después

Cuando necesitemos regresar en el tiempo porque borramos alguna línea de código pero no queremos pasarnos a otra rama porque nos daría un error al tener que pasar por ese "mal cambio" que hicimos en stage, podremos usar $ git stash y regresar así al cambio anterior que hicimos.

$ git stash es típico cuando hacemos cambios que no merecen una rama o no merecen un rebase si no que simplemente estamos probando algo y queremos volver rápidamente a la versión anterior que es la correcta.

git clean: limpiar tu proyecto de archivos no deseados

A veces creas archivos cuando estas realizando proyectos y que realmente no forman parte de nuestro directorio de trabajo, que no los deberias agregar y lo sabes.

  • Para saber que archivos son los que vamos a borrar tecleamos:
    $ git clean --dry-run
  • Para borrar todos los archivos listados (que no sean carpetas) tecleamos:
    $ git clean -f

git cherry-pick: traer commits viejos al head de un branch

Existe un mundo alternativo en el cual vamos avanzado en una rama pero necesitamos en main uno de estos avances de la rama, para esto utilizaremos el comando :
$ git cherry-pick IDCommit.
cherry-pick es una mala práctica porque significa que estamos reconstruyendo la historia, usa cherry-pick con conocimiento de causa. No saber que es lo que estas haciendo es peligroso.

Reconstruir commits en git con ammend

A veces hacemos un commit, pero resulta que no lo queremos mandar porque faltaba algo más. Utilizamos: $ git commit --amend
amend en inglés es remendar y lo que hará es que los cambios que hicimos nos los agregará al commit anterior.

git reset y reflog: únase en caso de emergencia

¿Que pasa cuando todo se rompe y no sabemos que está pasando? Con:
$ git reset HashDelHEAD
volveremos al estado en que el proyecto funcionaba:

  • $ git reset --soft HashDelHEAD: te mantiene lo que tengas en staging ahí.
  • $ git reset --hard HashDelHEAD: resetea absolutamente todo lo que tengas en staging.

git reset es una mala práctica, se recomienda no usarlo; debe ser el último recurso.

Buscar en archivos y commits de git con grep y log

A medida que se hace más grande el proyecto quieres ir buscando más cosas. Por ejemplo, ¿ Cuantas veces en nuestro proyecto buscamos la palabra color?

  • Con $ git grep -n color nos saldrá un output que nos dirá en que línea está lo que estamos buscando.
  • Con $ git grep -c color nos saldrá un output que nos dirá cuantas veces se repite esa palabra y en que archivos.
  • Si queremos buscar cuántas veces utilizamos un atributo de HTML lo hacemos con $ git grep -c "etiqueta html"
  • Si queremos buscar en los commits, por ejemplo la palabra cabecera lo hacemos con: $ git log -S cabecera