# Git

**git** es un software de control de versiones, un repositorio, pensado en mejorar la eficiencia y la confiabilidad del mantenimiento de versiones de aplicaciones cuando estas tienen un gran número de archivos de código fuente.&#x20;

Fue escrito por Linus Torvalds en 2005 para desarrollar 𝗟𝗶𝗻𝘂𝘅 𝗸𝗲𝗿𝗻𝗲𝗹 , y otros desarrolladores del kernel contribuyeron a su desarrollo inicial.

Es una especie de base de datos capaz de guardar las modificaciones por las que ha pasado un archivo y efectuar acciones sobre este historial, como recuperar una versión antigua. Está ampliamente extendido en la comunidad de desarrolladores y es muy recomendable su uso al empezar un proyecto.

<figure><img src="https://539580950-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FiKvwltOme7zTxep3LVyW%2Fuploads%2FYhD0tUznrjYCBoSB7t5I%2Fimage.png?alt=media&#x26;token=e00ac8f1-2495-4989-8c30-752192da8c3e" alt=""><figcaption><p>Esquema más sencillo del funcionamiento de GIT</p></figcaption></figure>

A parte de los dos entornos de local y remoto, Git tiene tres almacenamientos locales: un directorio de trabajo, un área de preparación y un repositorio local.&#x20;

1. 𝗪𝗼𝗿𝗸𝗶𝗻𝗴 𝗗𝗶𝗿𝗲𝗰𝘁𝗼𝗿𝘆 - Aquí es donde se trabaja y donde están los archivos (también llamado "*untracked*"). Todos los cambios de archivos aquí se marcarán y, si no se guardan en GIT, los perderá ya que GIT no reconoce  esos archivos.
2. 𝗦𝘁𝗮𝗴𝗶𝗻𝗴 𝗔𝗿𝗲𝗮 - Cuando guardes tus cambios con `git add`, GIT comenzará a rastrear y guardar tus cambios con archivos. Estos cambios se almacenan en el directorio .git. Luego, los archivos se mueven del *Working Directory* a la *Staging area*. Esto te permite preparar una instantánea antes de enviarla al historial oficial.
3. 𝗟𝗼𝗰𝗮𝗹 𝗥𝗲𝗽𝗼𝘀𝗶𝘁𝗼𝗿𝘆 - Es el área donde todo se guarda (confirma) en el directorio .git. Cuando quieras mover sus archivos del área de preparación al repositorio local, puede usar el comando `git commit.` Después de esto, su área de preparación estará vacía. Si desea ver qué hay en el repositorio local, intente con `git log`.&#x20;

<figure><img src="https://539580950-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FiKvwltOme7zTxep3LVyW%2Fuploads%2F9OtJTC10C2x3F4gyCxDC%2Fgit-workflow.gif?alt=media&#x26;token=5a39ea3e-f422-4de5-83d6-eb2336ecd18a" alt="" width="563"><figcaption><p>Funcionamiento de git</p></figcaption></figure>

## Comandos de GIT

Algunos comandos básicos de 𝗚𝗜𝗧 son: &#x20;

<table><thead><tr><th width="254">Comando GIT</th><th>Explicación</th></tr></thead><tbody><tr><td><strong><code>git clone</code></strong><code> &#x3C;url></code></td><td>Para hacer una copia de trabajo local de un repositorio remoto que ya existe, usa git clone que copia y descarga el repositorio al local. </td></tr><tr><td><code>𝗴𝗶𝘁 𝗶𝗻𝗶𝘁 nuevo-proyecto</code></td><td>Cree un nuevo repositorio llamado nuevo-proyecto de git en el directorio donde se encuentre</td></tr><tr><td><code>𝗴𝗶𝘁 𝗯𝗿𝗮𝗻𝗰𝗵 nueva-rama</code></td><td>Si se deja el nombre vacío se lista todas las ramas, sino, crea una nueva rama del repositorio local llamado "nueva-rama"</td></tr><tr><td><strong><code>git branch</code></strong><code> -d nueva-rama</code></td><td>Borra la rama "nueva-rama", usa -D (en mayuscula) para forzar el borrado si esta tiene cambios sin guardar.</td></tr><tr><td><strong><code>git branch</code></strong><code> -m antigua-rama nueva-rama</code></td><td>Cambia el nombre de "antigua-rama" a "nueva-rama"</td></tr><tr><td>𝗴𝗶𝘁 𝗰𝗵𝗲𝗰𝗸𝗼𝘂𝘁 nueva-rama</td><td>Cambiar a la rama "nueva-rama"</td></tr><tr><td><code>𝗴𝗶𝘁 𝗰𝗵𝗲𝗰𝗸𝗼𝘂𝘁 -b nueva-rama</code></td><td>Crea y cambia a la rama "nueva-rama", combinación de branch y chekout</td></tr><tr><td><p><strong><code>git checkout main</code></strong> </p><p><strong><code>git merge</code></strong><code> nueva-rama</code></p></td><td>Cambiar a la rama "main" o principal por defecto y fusionar la "nueva-rama" con esta</td></tr><tr><td><code>𝗴𝗶𝘁 𝗮𝗱𝗱 texto.txt</code></td><td>Agrega un nuevo archivo a la Staging area. Antes de que un archivo esté disponible para enviarse a un repositorio, el archivo debe agregarse al área de preparación. Si no es especifica el nombre se pasaran todos los archivos disponibles.</td></tr><tr><td><code>𝗴𝗶𝘁 𝗰𝗼𝗺𝗺𝗶𝘁 -m "Cambios principales"</code></td><td>Agrega cambios por etapas al repositorio local e incluye un mensaje con el parámetro "-m"</td></tr><tr><td><strong><code>git fetch --all</code></strong></td><td>Esto descarga una rama de otro repositorio, junto con todos los commits y archivos asociados. Sin embargo, no intenta integrar nada en el repositorio local. Esto permite inspeccionar los cambios antes de incorporarlos al proyecto.</td></tr><tr><td><code>𝗴𝗶𝘁 𝗽𝘂𝗹𝗹</code> </td><td>Extrae el código de su repositorio remoto al directorio local. Pulling es la versión automatizada de git fetch. Obtiene una rama de un repositorio remoto y la fusiona inmediatamente con la rama actual.</td></tr><tr><td><code>git log</code> </td><td>Permite revisar las revisiones anteriores de un proyecto. Ofrece una variedad de opciones de formato para mostrar instantáneas confirmadas.</td></tr><tr><td><code>𝗴𝗶𝘁 𝗽𝘂𝘀𝗵 --all</code></td><td>Pushing es exactamente lo opuesto a fetching. Permite mover una sucursal local a otro repositorio remoto, lo que facilita la publicación de contribuciones. Esto es similar al commit svn, pero en lugar de un único conjunto de cambios, envía una serie de commits.</td></tr><tr><td><code>𝗴𝗶𝘁 𝘀𝘁𝗮𝘁𝘂𝘀</code></td><td>Mostrar qué archivos están siendo rastreados (y no rastreados)  </td></tr><tr><td><code>𝗴𝗶𝘁 𝗱𝗶𝗳𝗳</code> </td><td>Mira la diferencia real en el código entre el Working Directory y la Staging area</td></tr></tbody></table>

Junto con los comandos GIT, puedes probar y usar algunos populares de herramientas de 𝗚𝗜𝗧 como son: *GitHub Desktop, SourceTree, TortoiseGit, Git Extensions, GitKraken, SmartGit, Tower, etc*.

## Instalación de GIT

En este ejemplo nos centraremos en distribuciones Ubuntu. Para la instalación sigue los siguientes pasos sencillos:

1. **Actualizar el Índice de Paquetes:** Antes de instalar cualquier nuevo paquete, es una buena práctica actualizar el índice de paquetes:

   ```bash
   sudo apt update
   ```
2. **Instalar Git:** Utiliza el siguiente comando para instalar Git:

   ```bash
   sudo apt install git
   ```

   Se te pedirá que ingreses tu contraseña de administrador para confirmar la instalación.
3. **Verificar la Instalación:** Puedes verificar que Git se haya instalado correctamente ejecutando el siguiente comando:

   ```bash
   git --version
   ```

   Esto debería mostrar la versión de Git que acabas de instalar.

## Ejemplos de funcionamiento

Vamos a ver varios procesos conjuntos que nos podríamos encontrar con Git.

### **Descargar el archivo del repositorio**

Para realizar esto usaremos mi repositorio de github de prueba:

1. Lo primero será clonar el repositorio completo (si aún no lo tienes):

   ```bash
   git clone https://github.com/aviladotgibert/gitprueba-sumatra.git
   ```

   Esto descargará todo el repositorio a tu máquina.
2. Navega a la carpeta del repositorio:

   ```bash
   cd gitprueba-sumatra
   ```

Si solo necesitamos un archivo y no el repositorio completo, es mejor usar alguna otra herramienta como `curl` o `wget` y en formato RAW. Por ejemplo, para descargar el archivo `README.md`:

```bash
curl -O https://raw.githubusercontent.com/aviladotgibert/gitprueba-sumatra/refs/heads/main/README.md
```

{% hint style="warning" %}
Si en el servidor no esta instalado python ni flask deberás instalarlos con:

```bash
sudo apt install python
pip install flask
```

Para ejecutar la aplicación usa:

```bash
python app.py
```

Y accede a `http://X.X.X.X:5000`
{% endhint %}

***

### **Subir un archivo actualizado al repositorio propio**

Cuando actualizas un archivo en tu repositorio local, puedes enviarlo al repositorio remoto que es lo interesante de Git:

1. **Asegúrate de estar en la rama correcta, p**or ejemplo:

   ```bash
   git checkout main
   ```
2. **Vamos a añadir una imagen a los archivos html para comprobar el cambio de estado**:

   ```bash
   wget -O snake.jpg "https://www.thainationalparks.com/img/species/2023/09/09/398028/trimeresurus-sumatranus-w-1500.jpg"
   ```

Ahora vamos al HTML y añadimos esto en algún punto:

```html
<img src="static/snake.jpg" alt="Trimeresurus sumatranus" style="width: 800px; height: auto;" />
```

Vamos con la actualización del proyecto en el repositorio remoto:

1. Verificamos primero el estado del repositorio comprobando qué archivos han cambiado o si hay archivos nuevos:

   ```bash
   git status
   ```
2. Añadimos el archivo al área de preparación (*staging area*):

   ```bash
   git add base.html
   ```

   Si quieres añadir todos los cambios:

   ```bash
   git add .
   ```

Puedes ver los cambios de los archivos del area de preparación con:

```bash
git diff --cached
```

Antes de hacer un commit deberemos hacer login (obviammente) para poder modificar cambios en el repositorio remoto:

```bash
git config --global user.email "you@example.com"
git config --global user.name "Your Name"
```

**Usar un token de acceso personal (PAT):** Si estás utilizando GitHub, GitLab o Bitbucket, ahora deberás usar un **token de acceso personal** (PAT) en lugar de tu contraseña para mayor seguridad. Para crear un token de acceso, sigue estos pasos en la plataforma correspondiente:

* **GitHub:** [Crear un token de acceso personal](https://github.com/settings/tokens)

Asegurate de darle permisos de modificación de repositorio y quédate con él.

1. **Crea un commit con un mensaje:**

   ```bash
   git commit -m "Añadida imagen culebreante"
   ```

2. **Revisa los commits hechos:**

```bash
git log
```

3. **Sube los cambios al repositorio remoto:**

```bash
git push origin main
git push --repo <repo> main
```

Ahora te pedirá el usuario y la *password*, para ello usa el token personal creado.

***

### **Subir un archivo actualizado a otro repositorio**

Podemos encontrarnos con el caso que el repositorio clonado no sea el nuestro principal por lo que en ese caso tenemos que realizar otra configuración:

#### **1. Verificamos la configuración actual del remoto**

Cuando clonas un repositorio, automáticamente se configura un remoto llamado `origin`, que apunta al repositorio original del que clonaste.

Para asegurarte de que está correctamente configurado, usa:

```bash
git remote -v
```

El resultado debería mostrar algo como:

```git
origin  https://github.com/otro-usuario/repositorio-clonado.git (fetch)
origin  https://github.com/otro-usuario/repositorio-clonado.git (push)
```

En este caso, ves que el repositorio remoto original es el del proyecto clonado. Si quieres subir tus cambios a **tu propio repositorio en GitHub**, necesitas cambiar o agregar un nuevo remoto:

**Opción A: Cambiar el remoto `origin`**

Si deseas usar tu propio repositorio como remoto, actualiza el URL del remoto `origin` para que apunte a tu repositorio en GitHub.

Primero, copia la URL de tu repositorio y cambia el remoto:

```bash
git remote set-url origin <https://github.com/tu-usuario/tu-repo.git>
```

Ahora verifica:

<pre class="language-bash"><code class="lang-bash"><strong>git remote -v
</strong></code></pre>

Deberías ver tu repositorio en lugar del original.

**Opción B: Agregar un nuevo remoto**

Si prefieres mantener el remoto original (`origin`) pero subir los cambios a tu propio repositorio, añade un nuevo remoto con un nombre diferente, como `mi-repo`:

```bash
git remote add mi-repo <https://github.com/tu-usuario/tu-repo.git>
```

Verifica que se haya añadido correctamente:

```bash
git remote -v
```

Ahora deberías ver algo como:

```git
origin    https://github.com/otro-usuario/repositorio-clonado.git (fetch)
origin    https://github.com/otro-usuario/repositorio-clonado.git (push)
mi-repo   https://github.com/tu-usuario/tu-repo.git (fetch)
mi-repo   https://github.com/tu-usuario/tu-repo.git (push)
```

#### **3. Sube tus cambios a tu repositorio**

Primero, asegúrate de que los cambios estén confirmados, verifica que todos los cambios estén preparados y confirmados:

1. Añade los cambios al área de preparación:

   ```bash
   git add .
   ```
2. Confirma los cambios:

   ```bash
   git commit -m "Descripción de los cambios realizados"
   ```

A continuación, si cambiaste `origin` para que apunte a tu propio repositorio:

```bash
git push origin main
```

O bien si añadiste un nuevo remoto (`mi-repo`):

```bash
git push mi-repo main
```

#### **4. Configura el seguimiento (si es necesario)**

Si la rama `main` (o la rama en la que estás trabajando) no existe en tu repositorio de GitHub, o si no está vinculada con el remoto, puedes configurarla con:

```bash
git push -u <nombre_remoto> main
```

O:

```bash
git push -u mi-repo main
```

Esto asegura que futuras ejecuciones de `git push` o `git pull` funcionen sin que tengas que especificar el remoto y la rama.

Ya por ultimo, deberías (Una vez subidos los cambios) ir al repositorio en GitHub y verificar que los archivos actualizados se hayan cargado correctamente.

***

### **Crear una ramificación de un proyecto**

Crear una nueva rama te permite trabajar en una copia del proyecto sin afectar la rama principal.

#### **Paso a paso:**

1. **Verifica las ramas existentes:**

   ```bash
   git branch
   ```
2. **Crear una nueva rama:**

   <pre class="language-bash"><code class="lang-bash"><strong>git branch tigre-sumatra
   </strong></code></pre>
3. **Cambiar a la nueva rama:**

   <pre class="language-bash"><code class="lang-bash"><strong>git checkout tigre-sumatra
   </strong></code></pre>

   O, si estás usando una versión moderna de Git, puedes crear y cambiar a la nueva rama directamente:

   ```bash
   git switch -c tigre-sumatra
   ```

   Ahora simplemente cambiamos archivos de proyecto, por ejemplo cambiando el titulo y la imagen por un tigre.

```bash
wget -O tiger.jpg "https://cdn.britannica.com/76/92676-050-F91A67C7/Sumatran-tiger-water.jpg"
```

<pre class="language-html"><code class="lang-html"><strong>&#x3C;img src="static/tiger.jpg" alt="Sumatran tiger" style="width: 800px; height: auto;" />
</strong></code></pre>

1. **Subir la nueva rama al repositorio remoto:**

   ```bash
   git add .
   git commit -ma "Añadido un cambio a rallas"
   git push -u origin tigre-sumatra
   ```

***

### **Unir y revisar errores de una ramificación de un proyecto**

Cuando una rama está lista para ser integrada en otra (por ejemplo, unir `tigre-sumatra` con `main`):

1. Antes de hacer un `merge`, puedes revisar qué cambios se introducirán:

   ```bash
   git diff main tigre-sumatra
   ```

2. Cambia a la rama base donde quieres unir los cambios:

   ```bash
   git checkout main
   ```

3. Une la rama en la que trabajaste con la rama base:

   ```bash
   git merge tigre-sumatra
   ```

4. Resolver conflictos (si los hay):

   * Si Git detecta conflictos en archivos, mostrará mensajes indicando los conflictos.
   * Abre los archivos conflictivos y busca marcas como estas:

     ```markdown
     <<<<<<< HEAD
     (tu versión actual)
     =======
     (cambios desde la otra rama)
     >>>>>>> rama_a_unir
     ```
   * Edita el archivo para resolver el conflicto y elimina las marcas.

5. Añade los archivos con conflictos resueltos:

   ```bash
   git add .
   ```

6. Completa el merge:

   ```bash
   git commit -m "Resueltos conflictos al unir tigre-sumatra"
   ```

7. Sube los cambios al repositorio remoto:

   ```bash
   git push origin main
   ```

***

### Juego sobre GIT

A continuación te dejo un enlace a un juego que te puede ayudar a coger experiencia con GIT:

{% embed url="<https://ohmygit.org/>" %}

{% embed url="<https://learngitbranching.js.org/?locale=es_AR>" %}
