Skip to content

Git

Hoy en día todo el mundo espera que utilices un sistema de gestión de control de versiones, que suele ser git.

Por eso las IDEs ya no se encargan de recuperar archivos borrados, o versiones anteriores de un archivo porque dan por supuesto que estás utilizando git.

¿Pero tú utilizas git? Más bien no.

Instal.la git:

Terminal window
> scoop install git

Configura git:

Terminal window
> git config --global init.defaultBranch main

Crea una carpeta test para empezar a trabajar y entra dentro de ella:

Terminal window
> mkdir test
> cd test

Crea un archivo hello.ts, escribe algo en él y borra el archivo:

Terminal window
> echo "console.log('Hello')" > hello.ts
> bun .\hello.ts
Hello
> rm .\hello.ts

Te puede parecer un ejercicio algo tonto, pero borrar lo que no toca suele ocurrir y no es nada divertido.

Esta vez vamos a versionar el directorio con git:

Terminal window
> git init -b main
Initialized empty Git repository in C:/Users/david/test/.git/

Vuelve ha hacer las mismas operaciones que antes:

Terminal window
> echo "console.log('Hello!')" > hello.ts
> bun .\hello.ts
Hello
> rm .\hello.ts

Cómo puedes verificar hemos vuelto a perder el archivo porque Git sólo guarda aquellos archivos que le has dicho que guarde!

Volvemos a empezar, pero esta vez preguntamos a git:

Terminal window
> git status
On branch main
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
hello.ts

Puedes ver que git sabe que el archivo hello.ts está en la carpeta, y te avisa de que no le está controlando.

Si quieres que git controle el archivo debes decir a git que lo haga con git add:

Terminal window
> git status
On branch main
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: hello.ts

Perfecto, ahora borramos el archivo y listo:

Terminal window
> rm hello.ts
> ls
>

Pues el archivo se ha borrado

¿Y que ha hecho git al respecto?

Terminal window
> git status
On branch main
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: hello.ts
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
deleted: hello.ts

Pues sabe que le habías dicho que controlara el archivo hello.ts y que lo has borrado

Git te da dos opciones:

  1. git rm hello.ts para que se olvide del archivo
  2. git restore hello.ts para restaurar el archivo

En este caso lo que queremos es recuperar el archivo:

Terminal window
> git restore hello.ts

Si has borrado el archivo ¿cómo es que git lo puede recuperar? Pues porque cuando ejecutaste git add hello.ts se guardó una copia en la carpeta .git

Si haces un ls -force puedes ver la carpeta oculta que creaste antes con la orden git init:

Terminal window
> ls -force
Directory: C:\Users\david\test
Mode LastWriteTime Length Name
---- ------------- ------ ----
d--h-- 8/3/2025 16:28 .git
-a---- 8/3/2025 16:28 46 hello.ts

Modifica el archivo hello.ts:

> echo "console.log('I think therefore I am.')" >> .\hello.ts
> bun .\hello.ts
Hello!
I think therefore I am.

Mira que ocurre cuando ejecutas git status:

Terminal window
> git status
On branch main
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: hello.ts
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: hello.ts

Git tiene una copia del archivo hello.ts que añadiste cuando hiciste git add, y también sabe que no se corresponde al archivo actual (alguien lo ha modificado).

Pero lo que hace más interesante a un sistema de control de versiones es que puedes ir guardando los cambios uno detrás de otro y volver atrás cuando quieras.

Si quieres guardar los cambios de forma permanente debes hacer un commit:

Terminal window
> git commit -m "Created hello.ts"
Author identity unknown
*** Please tell me who you are.
Run
git config --global user.email "you@example.com"
git config --global user.name "Your Name"
to set your account's default identity.

¡Y no te dejan hacer un commit!

Para realizar un commit debes configurar tu nombre y correo electrónico para que quede constancia de quién ha hecho qué. ¿Y a quién le interesa esto si yo ya se quién soy?

Pues porque git crea lo que se conoce como un repositorio que se puede compartir de forma colaborativa con otra gente y debe quedar constancia de quien ha hecho qué.

Configura tu nombre y correo electrónico:

Terminal window
> git config --global user.email "ddemingo@xtec.cat""
> git config --global user.name "David de Mingo"

Ayuda por el profesor. Para verificar que el alumno ha hecho lo que tenía que hacer ejecuta esta orden:

Terminal window
> git config --list | select-string user
user.email=david@optersoft.com
user.name=David de Mingo

Y ya puedes hacer un commit:

Terminal window
> git commit -m "Created hello.ts"
[main (root-commit) f6a40db] Created hello.ts
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 hello.ts

Si pides a git que te muestre el log puedes ver que David de Mingo ha añadido el archivo hello.ts al repositorio.

Terminal window
> git log
commit f6a40db05b638df4d2508631178daee11e8c8f6e (HEAD -> main)
Author: David de Mingo <david@optersoft.com>
Date: Sat Mar 8 16:37:50 2025 +0100
Created hello.ts
gitGraph
commit id:"f6a40db..."

Supongo que todavía no sabes exactamente de que va todo esto y lo encuentras poco interesante

Pues vamos a hacer un commit:

Terminal window
> echo "console.log('United we stand, divided we fall.')" >> .\hello.ts
PS C:\Users\david\Workspace\test> git add .\hello.ts
PS C:\Users\david\Workspace\test> git commit -m "Add quote from Aesop"
[main a2347c6] Add quote from Aesop
1 file changed, 0 insertions(+), 0 deletions(-)
mainf6a40db...a2347c6...

Y ahora otro commit:

Terminal window
> echo "console.log('Knowledge is power.')" >> .\hello.ts
> git add .\hello.ts
> git commit -m "Add quote from Sir Francis Bacon"
[main d57500e] Add quote from Sir Francis Bacon
1 file changed, 0 insertions(+), 0 deletions(-)
mainf6a40db...a2347c6...d57500e...

Si ejecutas git log puedes ver todas las modificaciones que se han guardado:

Terminal window
> git log
commit d57500e16b24c40ec5ce900364a840336ac7624a (HEAD -> main)
Author: David de Mingo <david@optersoft.com>
Date: Sat Mar 8 16:49:39 2025 +0100
Add quote from Sir Francis Bacon
commit a2347c6d6f0c70cf1befb3baddec0b75cf5178c2
Author: David de Mingo <david@optersoft.com>
Date: Sat Mar 8 16:46:40 2025 +0100
Add quote from Aesop
commit f6a40db05b638df4d2508631178daee11e8c8f6e
Author: David de Mingo <david@optersoft.com>
Date: Sat Mar 8 16:37:50 2025 +0100
Created hello.ts

Cada modificación (commit) tiene un identificador único tal y como puedes ver en la salida de git log.

Este identificador es un hash criptográfico (ver {% link “/security/cryptography/” %})

¿Qué debo hacer para poder ver las diferentes versiones del archivo hola?

Pedir a git que restaure la versión que tú quieres con la orden checkout:

Terminal window
> git checkout f6a4
...
HEAD is now at f6a40db Created hello.ts
> bun .\hello.ts
Hello
Terminal window
> git checkout a234
Previous HEAD position was f6a40db Created hello.ts
HEAD is now at a2347c6 Add quote from Aesop
> bun .\hello.ts
Hello
I think therefore I am.
United we stand, divided we fall.

Puedes ver que no hace falta que escribas todo el identificador, con los primeros dígitos es suficiente

Y para volver a la versión más actual puedes utilizar el identificador del commit o el de la rama (hablamos después):

Terminal window
> git checkout main
Previous HEAD position was a2347c6 Add quote from Aesop
Switched to branch 'main'
> bun .\hello.ts
Hello
I think therefore I am.
United we stand, divided we fall.
Knowledge is power.

Esto de los identificadores está muy bien por los ordenadores, pero las personas utilizamos nombres porque es más fácil para nosotros. ¿Te acuerdas de memoria de algún número de teléfono?

Git permite etiquetar commits con la etiqueta que nosotros queramos.

Por ejemplo, podemos etiquetar el commit actual con la etiqueta v0.0.1

Terminal window
> git tag -a v0.0.1 -m "We have added some quotes"

Y puedes etiquetar el commit “Created hello.ts” con la etiqueta v0.0.0 (esta vez tengo que indicar el id del commit):

Terminal window
> git tag -a v0.0.0 -m "Created hello" f6a4

Puedes ver que tenemos dos etiquetas:

Terminal window
> git tag
v0.0.0
v0.0.1
mainf6a40db...v0.0.0a2347c6...d57500e...v0.0.1

Y ver la información de un “tag”:

Terminal window
> git show v0.0.1
tag v0.0.1
Tagger: David de Mingo <david@optersoft.com>
Date: Sat Mar 8 17:05:48 2025 +0100
We have added some quotes
commit d57500e16b24c40ec5ce900364a840336ac7624a (HEAD, tag: v0.0.1, main)
Author: David de Mingo <david@optersoft.com>
Date: Sat Mar 8 16:49:39 2025 +0100
Add quote from Sir Francis Bacon

Y puedes cambiar de versión haciendo checkout del tag:

Terminal window
> git checkout v0.0.0
Previous HEAD position was d57500e Add quote from Sir Francis Bacon
HEAD is now at f6a40db Created hello.ts

Y volver al otro tag:

Terminal window
> git checkout v0.0.1
Previous HEAD position was f6a40db Created hello.ts
HEAD is now at d57500e Add quote from Sir Francis Bacon

También puedes borrar etiquetas;

Terminal window
> git tag -d v0.0.0
Deleted tag 'v0.0.0' (was 1a0f409)
> git tag
v0.0.1

Vuelve al main !!:

Terminal window
> git checkout main

Observación. Más información en Basics - Tagging

Quizás te sorprenda, pero git sólo lo utilizan los programadores

Y los programadores escribimos código que debe compilarse. ¿Y que significa compilar? Pues que se crean nuevos archivos y ejecutables, que necesitamos librerías, etc. y que naturalmente no se deben versionar !

¿Y cómo puede saber git que debe versionarse y que no debe versionarse? Pues no tiene ni idea, ¡es tu trabajo!

Por eso debes decir explícitamente qué archivos debe controlar con git add.

Pero también debes saber que un buen programador siempre encuentra la forma de hacer menos para conseguir más.

Por eso se añadió el flag --all en git add.

Crea dos archivos:

Terminal window
> echo "console.log('Blue moon')" > moon.ts
> echo "console.log('Red sea')" > sea.ts

Añade los ficheros a git:

Terminal window
> git add --all
PS C:\Users\david\Workspace\test> git status
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: moon.ts
new file: sea.ts

A continuación crea un proyecto con {% link “/ts/bun/” %}:

Terminal window
> bun init
> git add --all

Puedes ver que todo el contenido de la carpeta node_modules no se ha añadido:

Terminal window
> git status
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: .gitignore
new file: README.md
new file: bun.lockb
new file: index.ts
new file: moon.ts
new file: package.json
new file: sea.ts
new file: tsconfig.json

Esto es porque bun ha creado un fichero .gitignore donde constan todas las carpetas y ficheros que git ha de ignorar:

Terminal window
gc .\.gitignore | select-string node_modules
node_modules/

Haz un commit con los nuevos ficheros:

Terminal window
> git commit -a -m "Created bun project"
[main 165359c] Created bun project
8 files changed, 229 insertions(+)
create mode 100644 .gitignore
create mode 100644 README.md
create mode 100644 bun.lockb
create mode 100644 index.ts
create mode 100644 moon.ts
create mode 100644 package.json
create mode 100644 sea.ts

¡Y ahora empezamos una sesión de jardinería!

Cuando haces un proyecto de programación, cuando realizas un examen de programación, nunca te sale nada a la primera. Vas haciendo, te equivocas, vuelves atrás (debes deshacer cosas), intentas cosas nuevas, etc., y todo es un galimatías. La programación es así, y la mayoría de las labores de tu vida diaria son así.

Para poder trabajar en condiciones siempre debes avanzar desde una posición segura a otra posición segura. Y más importante, poder volver a una posición segura en la que todo funciona. Por eso git permite crear ramas de trabajo.

Crear una rama es muy fácil:

Terminal window
> git branch test
> git branch
* main
test

Ahora mismo las dos ramas (main es una rama como cualquier otra) son iguales porque ambas están apuntando al mismo commit.

Lo que vamos a hacer ahora es cambiar a la rama test y hacer un commit:

Terminal window
> git checkout test
Switched to branch 'test'

Puedes ver que cambiar de rama es hacer un checkout.

Terminal window
> echo "console.log('Keep your friends close, but your enemies closer.')" > corleone.ts
> git add .\corleone.ts
> git commit -m "Michael Corleone was right."
[test 38c6f10] Michael Corleone was right.
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 corleone.ts

Si volvemos a la rama main puedes ver que todo los commit nuevos de la rama test no aparecen.

Por tanto el archivo corleone.ts no existe:

Terminal window
> git checkout main
Switched to branch 'main'
> bun corleone.ts
error: Module not found "corleone.ts"

Si queremos borrar la rama test, git nos advierte de que no es conveniente porque todos los nuevos commits de la rama test se perderán.

> git branch -d test
error: the branch 'test' is not fully merged
hint: If you are sure you want to delete it, run 'git branch -D test'

De todas formas, ¿por qué querría borrar la rama test? Pues porque un proyecto sólo tiene un objetivo:

  1. Al final todo lo que funciona debe terminar en la rama principal
  2. Y lo que no ha funcionado y es un disparate debe eliminarse.

Si lo que he hecho en la rama test está bien y funcional, puedo fusionar los cambios en la rama principal:

Terminal window
> git merge test
Updating 165359c..38c6f10
Fast-forward
corleone.ts | Bin 0 -> 134 bytes
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 corleone.ts

Ahora ya tienes el archivo corleone.ts en la rama principal:

Terminal window
> bun .\corleone.ts
Keep your friends close, but your enemies closer.

Y puedes borrar la rama test:

Terminal window
> git branch -d test
Deleted branch test (was 38c6f10).

De todos modos muchos alumnos no ven la necesidad de crear una rama por algo tan simple.

Pues vamos a realizar una actividad bien divertida (al menos por el profe 🙄).

1. Crea un archivo main.ts que haga algo y realiza un commit del nuevo archivo.

2. Descarga una librería con bun add

3. Crea una nueva rama dev, cambia de rama, añade nuevas funciones a main.ts y haz un commit.

4. Vuelve a la rama main y haz un merge de la rama dev.

5. Haz un checkout del primer commit y verifica que es la primera versión de main.ts.

6. Vuelve al último commit y haz un tag v0.0.2

7. Modifica main.ts y haz otro commit.

8. Haz uno git log para ver todo el historial


El contingut d'aquest lloc web té llicència CC BY-NC-ND 4.0.

©2022-2025 xtec.dev