Git
Introducción
Section titled “Introducción”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
:
> scoop install git
Primeros pasos
Section titled “Primeros pasos”Configura git:
> git config --global init.defaultBranch main
Crea una carpeta test
para empezar a trabajar y entra dentro de ella:
> mkdir test> cd test
Crea un archivo hello.ts
, escribe algo en él y borra el archivo:
> echo "console.log('Hello')" > hello.ts> bun .\hello.tsHello> 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
:
> git init -b mainInitialized empty Git repository in C:/Users/david/test/.git/
Vuelve ha hacer las mismas operaciones que antes:
> echo "console.log('Hello!')" > hello.ts> bun .\hello.tsHello> 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
:
> git statusOn branch mainNo commits yetUntracked 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
:
> git statusOn branch mainNo commits yetChanges to be committed: (use "git rm --cached <file>..." to unstage) new file: hello.ts
Perfecto, ahora borramos el archivo y listo:
> rm hello.ts> ls>
Pues el archivo se ha borrado
¿Y que ha hecho git
al respecto?
> git statusOn branch mainNo commits yetChanges to be committed: (use "git rm --cached <file>..." to unstage) new file: hello.tsChanges 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:
git rm hello.ts
para que se olvide del archivogit restore hello.ts
para restaurar el archivo
En este caso lo que queremos es recuperar el archivo:
> 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
:
> 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.tsHello!I think therefore I am.
Mira que ocurre cuando ejecutas git status
:
> git statusOn branch mainNo commits yetChanges to be committed: (use "git rm --cached <file>..." to unstage) new file: hello.tsChanges 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).
Commit
Section titled “Commit”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:
> 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:
> 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:
> git config --list | select-string user
user.email=david@optersoft.comuser.name=David de Mingo
Y ya puedes hacer un commit
:
> 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.
> git logcommit 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:
> echo "console.log('United we stand, divided we fall.')" >> .\hello.tsPS C:\Users\david\Workspace\test> git add .\hello.tsPS 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(-)
Y ahora otro commit:
> 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(-)
Si ejecutas git log
puedes ver todas las modificaciones que se han guardado:
> git logcommit 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 a2347c6d6f0c70cf1befb3baddec0b75cf5178c2Author: David de Mingo <david@optersoft.com>Date: Sat Mar 8 16:46:40 2025 +0100
Add quote from Aesop
commit f6a40db05b638df4d2508631178daee11e8c8f6eAuthor: David de Mingo <david@optersoft.com>Date: Sat Mar 8 16:37:50 2025 +0100
Created hello.ts
Checkout
Section titled “Checkout”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
:
> git checkout f6a4...HEAD is now at f6a40db Created hello.ts
> bun .\hello.tsHello
> git checkout a234Previous HEAD position was f6a40db Created hello.tsHEAD is now at a2347c6 Add quote from Aesop
> bun .\hello.tsHelloI 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):
> git checkout mainPrevious HEAD position was a2347c6 Add quote from AesopSwitched to branch 'main'
> bun .\hello.tsHelloI 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
> 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):
> git tag -a v0.0.0 -m "Created hello" f6a4
Puedes ver que tenemos dos etiquetas:
> git tagv0.0.0v0.0.1
Y ver la información de un “tag”:
> git show v0.0.1tag v0.0.1Tagger: 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:
> git checkout v0.0.0Previous HEAD position was d57500e Add quote from Sir Francis BaconHEAD is now at f6a40db Created hello.ts
Y volver al otro tag:
> git checkout v0.0.1Previous HEAD position was f6a40db Created hello.tsHEAD is now at d57500e Add quote from Sir Francis Bacon
También puedes borrar etiquetas;
> git tag -d v0.0.0Deleted tag 'v0.0.0' (was 1a0f409)> git tagv0.0.1
Vuelve al main
!!:
> git checkout main
Observación. Más información en Basics - Tagging
Ignore
Section titled “Ignore”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:
> echo "console.log('Blue moon')" > moon.ts> echo "console.log('Red sea')" > sea.ts
Añade los ficheros a git
:
> git add --allPS C:\Users\david\Workspace\test> git statusChanges 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/” %}:
> bun init> git add --all
Puedes ver que todo el contenido de la carpeta node_modules
no se ha añadido:
> git statusChanges 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:
gc .\.gitignore | select-string node_modules
node_modules/
Haz un commit con los nuevos ficheros:
> 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.
Branch
Section titled “Branch”Crear una rama es muy fácil:
> 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:
> git checkout testSwitched to branch 'test'
Puedes ver que cambiar de rama es hacer un checkout
.
> 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:
> git checkout mainSwitched to branch 'main'
> bun corleone.tserror: 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 testerror: the branch 'test' is not fully mergedhint: 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:
- Al final todo lo que funciona debe terminar en la rama principal
- 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:
> git merge testUpdating 165359c..38c6f10Fast-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:
> bun .\corleone.tsKeep your friends close, but your enemies closer.
Y puedes borrar la rama test
:
> git branch -d testDeleted 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 🙄).
Actividad
Section titled “Actividad”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