Todos hemos tenido esa carpeta: proyecto_final.zip, proyecto_final_v2.zip, proyecto_final_v2_BIS_esto_sí.zip. Cada copia era un intento de tener un botón de deshacer para el proyecto entero. Cada copia fallaba en lo mismo: no sabías qué cambió de una a la otra, ocupaban el doble y, si el disco moría, se llevaba todo el trabajo a la vez.

Git es la solución seria a ese problema, y no es una herramienta para grandes empresas: es una herramienta para cualquiera que cree archivos que puede arrepentirse de haber modificado. Ha funcionado así desde 2005, cuando Linus Torvalds —el creador de Linux— la escribió en cuestión de semanas para gestionar el código del kernel. Hoy, cualquier proyecto de software que conozcas pasa por Git.

Esta entrada va de la teoría al botón: primero cómo piensa Git, después cómo instalarlo y configurarlo en un ordenador nuevo, y por último un manual de uso completo sobre un repositorio real: el de mi propia página de documentación en GitHub, cuyos archivos no son nada exótico —HTML, CSS y un README—. Si eso puede versionarse y publicarse con Git, cualquier proyecto tuyo también.

Por qué Git, aunque trabajes solo

Lo primero que hay que desmontar: Git no es “para equipos”. Un equipo lo necesita por lo de compartir, sí, pero la mitad de lo que hace Git importa incluso cuando el autor eres tú y solo tú:

  • Historial completo. Cada commit es una fotografía del proyecto: qué era, qué cambió, cuándo y por qué. Puedes ver cualquier versión de cualquier archivo, de hace diez minutos o de hace dos años.
  • Viaje al pasado. ¿Rompiste algo que funcionaba hace tres días? Vuelves. Sin resaca, sin recombinar zips a mano.
  • Experimentos sin riesgo. Las ramas te permiten ensayar una idea en un universo paralelo; si sale bien se une al proyecto y, si no, se descarta y main no se entera.
  • Copia de seguridad de verdad. Con un repositorio remoto (GitHub, GitLab), no solo tienes los archivos respaldados: tienes el historial respaldado, que es la parte que más llora un pendrive.
  • Trabajar con IA sin bailar al borde del acantilado. Cuando un agente edita tu código —y este blog va de eso—, el commit previo es la diferencia entre “deshago lo que hizo el agente en un comando” y “reinstalo el proyecto”. Esto tiene su propia sección más abajo.

Cómo piensa Git: cuatro ideas y cero cábala

Git tiene fama de críptico porque la gente memoriza comandos sin entender el modelo. El modelo es pequeño. Cuatro ideas.

1. Git guarda fotografías, no cambios

Un commit no guarda “he cambiado tres líneas”. Guarda una foto completa del proyecto en ese momento + quién la hizo, cuándo y a partir de qué foto anterior. Esa cadena de fotos es el historial. Cada foto tiene un identificador único —un hash como c8a4421— que se calcula a partir de su contenido y del commit anterior: cambiar una sola coma cambia ese hash y todos los que vienen detrás. Por eso el historial es verificable: no se puede alterar una fotografía antigua sin que la cadena deje de cuadrar.

2. Tus cambios viajan por cuatro zonas

Entre “estoy editando” y “está respaldado en GitHub” hay dos paradas intermedias. Entender el mapa despeja la mitad de la confusión:

  1. Directorio de trabajoTu editor, sin red

    Aquí editas libremente. Git todavía no ha registrado nada de esto.

  2. git add← git restore --staged
  3. Área de preparaciónLa próxima fotografía

    La lista de lo que entrará en el siguiente commit.

  4. git commit← git revert
  5. Repositorio localLa fototeca: el historial

    Vive en tu disco, dentro de .git. Funciona sin conexión.

  6. git push← git pull
  7. Repositorio remotoLa fototeca compartida

    GitHub o GitLab: copia de seguridad compartida y publicable.

Las cuatro zonas de Git. El cambio avanza de izquierda a derecha con add, commit y push; y hay comandos para retroceder entre ellas.
  • Directorio de trabajo: lo que ves en tu editor. Ahí fallas, escribes y rectificas. Git no guarda nada de este estado: es tu borrador.
  • Área de preparación (staging): con git add eliges exactamente qué archivos entran en la próxima fotografía. Es la diferencia entre “guarda todo” y “guarda solo el cambio del menú”.
  • Repositorio local: git commit sella la fotografía y la añade al historial, que vive en una carpeta oculta .git dentro de tu proyecto.
  • Repositorio remoto: git push manda tus commits nuevos a GitHub o GitLab. No edita ahí tus archivos: sincroniza historial.

Todo lo demás son detalles de cómo mover cosas entre estas cuatro zonas. Cuando te bloquees, pregúntate: “¿en qué zona está mi cambio, y hacia dónde quiere ir?”. El comando sale solo.

3. Todo ocurre primero en tu ordenador

Git es distribuido: tu repositorio local es un repositorio completo, no un “fragmento sincronizado”. Puedes hacer commits, crear ramas y examinar el historial en un tren sin wifi. El remoto no es “la fuente de la verdad”: es un punto de sincronización y respaldo compartido. Y eso tiene una consecuencia preciosa para los impacientes: recuperar un archivo borrado no requiere llamar a nadie, ni estar en línea.

4. Las ramas son punteros, no copias

Crear una rama en Git es prácticamente gratis: es mover un puntero, no copiar el proyecto. Por eso se ramifica tan a menudo —cada funcionalidad, cada experimento, cada arreglo—. La rama principal suele llamarse main.

Instalación: cinco minutos

A fecha de este artículo (octubre de 2026), la última versión estable es Git 2.56.0 (septiembre de 2026; Git for Windows publicó su compilación 2.56.0.windows.2 en octubre), pero no hace falta obsesionarse: cualquier versión reciente de los últimos dos años sirve para todo lo de esta guía.

Comprueba si ya lo tienes abriendo una terminal (en Windows, PowerShell) y escribiendo:

git --version
# git version 2.56.0

Si responde, saltas a la configuración. Si no:

# Windows (recomendado, con Git for Windows incluidos Git Bash y gestor de credenciales)
winget install --id Git.Git -e
# macOS (con Homebrew)
brew install git

# Linux (Debian / Ubuntu)
sudo apt install -y git

# Linux (Fedora)
sudo dnf install -y git

La instalación de Windows trae, además, Git Bash: una terminal propia con los mismos comandos que el resto de sistemas. Los instaladores están siempre en git-scm.com/downloads, con instrucciones paso a paso por plataforma.

Configuración inicial: una vez por ordenador

Git necesita saber quién eres para poner tu firma en cada commit. Se configura una vez, globalmente, y vale para todos tus proyectos:

# Identidad (usa el mismo email que tu cuenta de GitHub o GitLab)
git config --global user.name "Tu Nombre"
git config --global user.email "[email protected]"

# Que las ramas nuevas se llamen main (Git aún usa master si no lo cambias)
git config --global init.defaultBranch main

# Final de línea: true solo en Windows nativo; en macOS, Linux o WSL usa "input"
git config --global core.autocrlf true

# Comprobación: lista todo lo configurado
git config --global --list

El detalle de core.autocrlf es la primera trampa para quien empieza en Windows: Git normaliza los saltos de línea a Unix (LF) al guardar, y Windows los edita históricamente como CRLF. La configuración anterior traduce los saltos automáticamente al hacer commits y pulls, y evita archivos que “cambian solos” en el git status.

Lo siguiente es autenticarse con GitHub. En Windows, Git for Windows incluye Git Credential Manager: en el primer git push se abre el navegador, inicias sesión y la credencial queda guardada. En macOS y Linux, el ayudante nativo suele pedir usuario y token personal (PAT) —GitHub ya no acepta contraseñas desde 2021—, así que mucha gente prefiere SSH: generas una clave, la pegas en GitHub y listo.

# SSH: generar una clave (una vez por ordenador, valores por defecto)
ssh-keygen -t ed25519 -C "[email protected]"

# ver la clave pública para copiarla a GitHub → Settings → SSH and GPG keys
cat ~/.ssh/id_ed25519.pub

# comprobar que GitHub te reconoce
ssh -T [email protected]

Si quieres profundizar en montar el entorno completo —WSL2, terminal, GitHub CLI—, ya lo cubrimos paso a paso en la guía de equipo para programar con IA.

Proyecto local: del suelo al primer commit

Vamos a hacerlo con un caso real. Imagina que estás montando una página de documentación, como la de mi repositorio de la portada: HTML, CSS y a correr. Empieza un proyecto así:

# crear la carpeta y entrar
mkdir pagina-documentacion
cd pagina-documentacion

# convertir la carpeta en un repositorio Git
git init

Tras el git init aparece el aviso de que se ha inicializado el repositorio con una rama main (gracias a la configuración anterior) y se crea una carpeta oculta .git: toda la magia de Git vive ahí dentro. Regla de oro: no la toques, no la borres y no la metas a mano en copias de seguridad — el historial Git ya lo respalda él solo.

Crea unos archivos —por ejemplo index.html y styles.css— y pregunta qué opina Git:

git status
On branch main

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        index.html
        styles.css

nothing added to commit but untracked files present (use "git add" to track)

Untracked significa “existe en tu carpeta pero Git todavía no lo vigila”. Vamos a hacerle una foto:

# 1) seleccionar qué pasa a la fotografía
git add index.html styles.css

# (o directamente todo lo nuevo/modificado del proyecto: git add .)

# 2) sellar la fotografía con un mensaje
git commit -m "Primer commit: página base con estilos"
[main (root-commit) a1f3e90] Primer commit: página base con estilos
 2 files changed, 42 insertions(+)
 create mode 100644 index.html
 create mode 100644 styles.css

Ese a1f3e90 es el identificador del commit: la primera foto queda sellada. Edita algo, por ejemplo el menú, y observa el ciclo completo:

git status      # qué ha cambiado desde la última foto
git diff        # el cambio línea a línea, antiguo frente a nuevo
git add .       # seléctalo todo
git diff --staged   # lo que está preparado y entrará en el commit
git commit -m "Actualiza el menú de navegación"
git log --oneline   # el historial resumido

git diff muestra lo que aún no has preparado; git diff --staged muestra exactamente lo que llevará el próximo commit. Es la pareja que conviene mirar antes de pulsar commit.

Y eso es Git. El resto de este artículo repite ese ciclo en escenarios cada vez más exigentes: a distancia, con varios pares de manos sobre el teclado y con la herramienta de deshacer expuesta.

Qué no debe entrar nunca en el repositorio

Hay archivos que no se versionan: dependencias que se reinstalan solas (node_modules/), resultados de compilación (dist/), registros y, sobre todo, secretos (.env, claves, tokens). Para eso está .gitignore, un archivo de texto en la raíz con los patrones que Git debe ignorar:

# .gitignore
node_modules/
dist/
.env
*.log
git status            # los archivos ignorados ya no aparecen
git status --ignored  # comprobar qué está ignorando Git

Dos advertencias que ahorran disgustos. La primera: .gitignore solo afecta a archivos que Git aún no rastrea; si ya habías hecho commit de un .env, sigue en el historial y hay que sacarlo con git rm --cached .env. La segunda: si un secreto llegó a un repositorio público, bórralo y cambia la clave; borrar el commit no basta, porque el historial pudo copiarse.

Commits que valen: la brújula del proyecto

Un commit vale lo que vale su mensaje. Cómo distinguir:

# commits malos (seis meses después no sabrás nada)
"cambios"
"vale ya funciona"
"final real este sí"

# commits buenos (cuentan el qué y el porqué en una línea)
"Fix: limita el carácter máximo del buscador a 80 para móvil"
"Añade evento click al menú lateral para pantallas medianas"

Dos reglas hacen el 80 % del trabajo:

  1. Commits pequeños y con un propósito. “Arreglo el buscador y de paso actualizo dependencias” son dos commits, no uno. Un commit pequeño es un punto de retorno fino; uno enorme es un botón que desactiva un bloque entero.
  2. Mensaje en imperativo, una línea útil. “Añade tabla de contenidos” dice mejor qué hace que “tabla de contenidos añadida”. Si hace falta explicar por qué, segunda línea en blanco y después el detalle.

Hay un estándar popular, los Conventional Commits (feat:, fix:, docs:…), que algunos proyectos exigen; para empezar, no es imprescindible: es mejor un mensaje claro en lenguaje propio que un prefijo ceremonioso sin contenido.

Comandos de lectura del historial que usarás cada semana:

git log --oneline --graph --all   # historial compacto con visualización de ramas
git show a1f3e90                  # qué hizo exactamente este commit

El salto al remoto: GitHub como casa del proyecto

Tu repositorio local es perfecto para ti. El remoto añade tres cosas: respaldo en otro sitio, colaboración y publicación. Veamos las dos situaciones posibles con un caso real: mi repositorio fcc-cp-technicalDocumentationPage, una página de documentación técnica publicada en jamolpe88.github.io/fcc-cp-technicalDocumentationPage.

Página de documentación sobre Git publicada en GitHub Pages, con menú lateral de temas y una introducción al control de versiones
La página del repositorio, servida por GitHub Pages. El mismo proyecto que vive en la rama main es la web que ve cualquiera: Git no solo guarda el código, también es el mecanismo de publicación.Fuente: GitHub Pages

Caso A: ya tienes código local y quieres subirlo

  1. En GitHub: New repository → nombre → Public → sin README ni .gitignore (el repo remoto debe nacer vacío para poder recibir tu historial intacto).
  2. Conecta y empuja:
git remote add origin https://github.com/TU-USUARIO/mi-repo.git
git push -u origin main

origin es simplemente el apodo por convención del remoto principal. El -u de la primera subida enlaza tu rama main local con origin/main para siempre: después bastará con git push.

Caso B: el proyecto ya está en remoto y quieres bajártelo

git clone https://github.com/JaMoLpE88/fcc-cp-technicalDocumentationPage.git
cd fcc-cp-technicalDocumentationPage

Clonar no descarga “los archivos”: descarga el proyecto con todo su historial, ramas incluidas. El ejemplo real tiene la estructura común de una página web sencilla:

fcc-cp-technicalDocumentationPage/
├── index.html      # la página de documentación
├── styles.css      # estilos generales
├── prism.css       # resaltado de sintaxis del código
├── prism.js        # idem, la parte JavaScript
└── README.md       # descripción del proyecto
Página del repositorio en GitHub con la rama main, el historial de un commit y los archivos README.md, index.html, prism.css, prism.js y styles.css
El repositorio remoto real: rama main, un único commit y cinco archivos. La columna derecha enlaza la versión publicada. Es todo lo que hace falta para tener un proyecto versionado y accesible.Fuente: GitHub

Y, como tiene activado GitHub Pages desde la rama main, lo que se sube ahí es lo que se publica, sin trucos: esa es exactamente la conexión entre versionado y despliegue. Para comprobar qué remotos tienes conectados:

git remote -v

GitLab, Bitbucket o un servidor propio funcionan exactamente igual: cambia la URL y el flujo es idéntico; solo cambian los nombres de las interfaces.

El bucle diario

A partir de ahí, la vida de un proyecto con remoto es un bucle de cuatro tiempos:

git pull                          # 1) traer lo que hayan hecho otros
# ... editas, creas, borras ...   # 2) trabajar en tu copia local
git add .                         # 3) preparar tus cambios y sellarlos
git commit -m "Mejora la tabla de contenidos"
git push                          # 4) compartir con el mundo

Si al hacer push te dice que estás “detrás” del remoto, no te empeñes: es el paso 1 que falta. pull antes del push, siempre.

Ramas: experimentar sin facturas

Vamos a usar el repositorio real como guion. Para practicar, clónalo en una carpeta de pruebas y trabaja con tu propio fork (o con un repositorio tuyo): el mío es solo el ejemplo, y no debes escribir en él. Supón que quieres reorganizar la tabla de contenidos de la página, pero no quieres dejar main, que todo el mundo visita, a medias. Se crea una rama:

# desde main, creamos la rama y nos cambiamos a ella
git switch -c mejora-tabla-contenidos
Switched to a new branch 'mejora-tabla-contenidos'

En esta rama editas index.html, y tus commits van apilándose solo en esa rama:

git add .
git commit -m "Agrupación y numeración en la tabla de contenidos"
git push -u origin mejora-tabla-contenidos

Mientras tanto, main sigue intacta y publicable. Si la experimentación no convence: git switch main y a otra cosa — la rama se puede borrar sin dejar cicatriz. Si convence, se fusiona:

git switch main
git merge mejora-tabla-contenidos    # trae los cambios de la rama a main
git push                            # y al remoto

# cuando ya no la necesitas, borra la rama local
git branch -d mejora-tabla-contenidos
rama: mejora-tabla-contenidosmaina1f3e90Primer commitc8a4421Página basef23d7b0Rama creada91e5c44Mejoras en la tablad7b21afmergee3f9d32Sigue main
Un commit es un nodo; cada rama, una línea de nodos. El merge une las dos historias en un punto del grafo.

Lo interesante del grafo: Git registra que esos cambios vienen de una rama concreta y por qué se fusionan. Si algo empeora, el merge es el punto exacto del pasado al que apuntar.

¿Y los conflictos?

Si dos ramas editan la misma línea del mismo archivo, Git no decide por ti: marca el conflicto y te enseña una ventana:

<<<<<<< HEAD
<nav id="navbar">
  <a href="#introduccion">Introducción</a>
  <a href="#sintaxis">Sintaxis</a>
</nav>
=======
<nav id="navbar" class="compacta">
  <a href="#introduccion">Intro</a>
  <a href="#sintaxis">Sintaxis</a>
</nav>
>>>>>>> mejora-tabla-contenidos

No es un error: es una pregunta de diseño que Git no puede responder solo. Eliges qué versión (o combinación) quieres a mano, borras los marcadores, y rematas el ciclo:

git add .
git commit -m "Resuelve conflicto del navegador con versión compacta"

En GitHub, además del merge local existe el flujo profesional: subes la rama, abres una Pull Request, alguien (o el CI) revisa los cambios y se fusionan con un botón. Para proyectos con más de un humano, es el flujo de serie.

Cuando el proyecto llega a un hito: etiquetas

Los commits marcan pasos; las etiquetas marcan versiones. Cuando el proyecto alcanza un punto que quieres recordar —una primera publicación, un lanzamiento— se crea una etiqueta anotada:

git tag -a v1.0.0 -m "Primera versión publicada"
git push origin v1.0.0    # las etiquetas no viajan con un push normal
git tag                   # listar las etiquetas existentes

A diferencia de una rama, una etiqueta no se mueve: queda anclada al commit que marcaba ese hito. GitHub las convierte en Releases, con notas y descargas, y git switch v1.0.0 te devuelve exactamente al estado de esa versión (quedarás en detached HEAD, modo consulta: si quieres cambiar algo, crea una rama desde ahí).

Volver atrás: el manual de supervivencia

Aquí está el tesoro real. Casos ordenados por gravedad, del yeso al quirófano:

Escenario Comando Nota
Destruí un archivo, aún no hice commit git restore index.html Lo devuelve a la versión del área de preparación (normalmente, la del último commit)
Añadí de más al staging git restore --staged styles.css Lo saca del área de preparación, no borra nada
Se me olvidó algo en el último commit git commit --amend Solo si no has hecho push
Quiero anular un commit ya publicado git revert d7b21af Crea un “commit inverso”; seguro con remoto
Descartar commits locales y volver a un punto anterior git reset --hard a1f3e90 Destruye commits posteriores; solo en local
Guardo trabajo a medias y cambio de contexto git stash / git stash pop Aparcamiento temporal del directorio

Dos aclaraciones importantes para perder el miedo (o recuperarlo, según el caso):

revert no es reset. revert deshace el efecto de un commit añadiendo otro commit que lo anula: el historial sigue intacto y todos los que ya hayan hecho pull pueden seguir trabajando. Es la forma segura de deshacer en cualquier commit compartido. reset --hard, en cambio, reescribe el presente: borra commits posteriores. Es muy útil en local y muy traicionero si se mezcla con remoto: obligaría a un push --force que no le hace bien a nadie.

El comando que te devuelve hasta lo “perdido”: git reflog

Hay un último salvavidas que casi nadie conoce: Git anota cada movimiento de tu cabecera —cada commit, cada reset, cada cambio de rama— en un diario, y ese diario sobrevive a casi todo durante unas semanas:

git reflog
e3f9d32 (HEAD -> main) HEAD@{0}: commit: Sigue main
d7b21af HEAD@{1}: merge mejora-tabla-contenidos
a1f3e90 HEAD@{2}: reset: moving to a1f3e90
91e5c44 HEAD@{3}: commit: Mejoras en la tabla de contenidos

Si hiciste un reset --hard y crees que has perdido commits, lo verás ahí: HEAD@{3} te devuelve ese estado con git reset --hard 91e5c44 o, más suave, con git branch rescatado 91e5c44, que crea una rama en ese punto. Ojo con la letra pequeña: el reflog recupera commits, no cambios que nunca llegaste a commitear; esos no están en ninguna fotografía. Esta es la culminación de la idea con la que empezó el artículo: “he borrado commits” deja de ser un drama y pasa a ser un error de una línea. (Por defecto, estas entradas del diario se conservan entre 30 y 90 días; no esperes meses.)

Git cuando escribe la IA

Si has llegado leyendo sin fijarte en el asunto del blog, esto es para ti. Cuando quien edita el código es un agente —Claude Code, Codex, OpenCode—, Git deja de ser “buena práctica” y se convierte en cinturón de seguridad:

  1. Commit limpio antes de que el agente toque nada. Sin ese punto de partida, no puedes distinguir “lo había cambiado yo” de “cambió el agente”. Con un commit previo, git diff te enseña exactamente lo que ha hecho la máquina.
  2. Revertir el trabajo de un agente es un comando. Si la modificación no te convence, no hace falta “arreglarla” casi nunca: git restore . si no está confirmada; si el agente ya la había preparado con git add, usa git restore --staged . y después git restore .. Si ya está en un commit, git revert. Experimentar con agentes se vuelve literalmente gratis.
  3. Ramifica por experimento. Cada intento del agente en su rama; al final, haces el merge (o no) con lo que haya rendido. Así puedes iterar varios intentos sin ir deshaciendo uno a uno.
  4. Los commits pequeños son contexto. Un historial limpio, con mensajes que explican el por qué, es material con el que el propio agente trabaja mejor: los agentes pueden leerlo para entender el proyecto.
  5. Verificación antes que fe. El agente propone; los tests, el build y tus ojos sobre git diff disponen. Nunca hagas push de código que no hayas revisado.

Está en la línea de lo que contábamos en la guía de equipo: un buen historial Git es lo que hace que un agente rinda de verdad en producción.

Chuleta: los comandos que se usan de verdad

Quiero… Comando
Empezar un proyecto nuevo versionado git init
Bajarme un proyecto existente con su historial git clone URL
Ver qué ha cambiado git status
Ver los cambios línea a línea git diff
Preparar una fotografía git add .
Sellarla git commit -m "mensaje"
Ver el historial git log --oneline --graph --all
Crear y cambiar de rama git switch -c nombre-rama
Volver a main git switch main
Fusionar una rama git merge nombre-rama
Subir al remoto git push
Traer del remoto git pull
Ver mis remotos apuntados git remote -v
Descartar cambios locales git restore archivo
Anular un commit publicado git revert hash
Guardar trabajo a medias temporalmente git stash y luego git stash pop
Recuperar lo “perdido” git reflog

Glosario mínimo

  • Repositorio: la carpeta del proyecto + su historial completo (dentro de la carpeta oculta .git).
  • Commit: fotografía sellada del proyecto, con autor, fecha y mensaje.
  • Rama (branch): línea de trabajo paralela; un puntero, no una copia.
  • HEAD: el punto del historial donde te encuentras ahora mismo.
  • main: la rama principal por convención (antes master).
  • origin: apodo del repositorio remoto principal.
  • Staging: área de preparación; los archivos listos para el próximo commit.
  • Merge: unión de las historias de dos ramas.
  • Pull Request: petición de fusión en GitHub/GitLab, con revisión y CI.
  • Clone: copia completa de un repositorio, historial incluido.

Fuentes y para seguir aprendiendo