← Volver al Blog
02 April, 2026 Por pacheco

Git de Cero a Experto: Curso Completo de Control de Versiones


¿Por qué deberías dominar Git?

Imagina trabajar durante horas en un proyecto y, por un error, borrar todo lo que hiciste. O imagina que tú y otros tres desarrolladores modifican el mismo archivo al mismo tiempo y sus cambios se pisan entre sí. Sin control de versiones, estas situaciones son desastres sin solución. Con Git, son situaciones manejables en segundos.

Git es la herramienta de control de versiones más usada en el mundo. Está presente en prácticamente todos los proyectos de software profesional. Aprenderlo no es opcional; es la base del trabajo colaborativo moderno.

"El código que no está en control de versiones no existe."
— Principio fundamental del desarrollo profesional

1. ¿Qué es el Control de Versiones?


Un Sistema de Control de Versiones (VCS) registra cada cambio que haces en tus archivos a lo largo del tiempo. Esto te permite:

  • Ver el historial completo de qué cambió, cuándo y quién lo cambió
  • Revertir archivos o el proyecto completo a un estado anterior
  • Comparar cambios a lo largo del tiempo
  • Trabajar en paralelo con otras personas sin conflictos
  • Experimentar con nuevas ideas sin miedo a romper lo que ya funciona

Tipos de VCS

Tipo Ejemplo Descripción
Local RCS Solo en tu máquina. Sin colaboración.
Centralizado SVN, CVS Un servidor central. Si cae, todos pierden acceso.
Distribuido Git, Mercurial Cada desarrollador tiene una copia completa. Sin punto único de fallo.

2. ¿Qué es Git?

Git logo y terminal

Git es un sistema de control de versiones distribuido, gratuito y de código abierto, creado por Linus Torvalds en 2005 para gestionar el desarrollo del kernel de Linux. Hoy es el estándar de la industria.

Características clave de Git

  • Distribuido: cada clon es un repositorio completo con todo el historial
  • Rápido: la mayoría de operaciones son locales, sin red
  • Íntegro: todo está verificado por checksum SHA-1; es imposible corromper datos sin que Git lo detecte
  • No destructivo: Git casi nunca borra datos; los "commits" son permanentes
  • Branching barato: crear una rama toma microsegundos y consume mínima memoria

Git vs GitHub vs GitLab vs Bitbucket

Esta confusión es muy común entre principiantes:

  • Git es la herramienta de línea de comandos que corre en tu máquina
  • GitHub / GitLab / Bitbucket son plataformas en la nube que alojan repositorios Git remotos y agregan herramientas como pull requests, CI/CD, issues, wikis, etc.

Puedes usar Git perfectamente sin ninguna de esas plataformas. Pero en la práctica, siempre usarás alguna para colaborar con equipos.

3. Instalación y Configuración Inicial


Instalación por sistema operativo

# macOS (con Homebrew)
brew install git

# Ubuntu / Debian
sudo apt update && sudo apt install git -y

# Fedora / RHEL
sudo dnf install git -y

# Windows — descargar desde:
https://git-scm.com/download/win

# Verificar instalación
git --version
# git version 2.45.0

Configuración obligatoria — identidad

Lo primero que debes hacer después de instalar Git es decirle quién eres. Esta información queda grabada en cada commit que hagas:

# Configurar nombre y email globalmente (para todos tus proyectos)
git config --global user.name "Tu Nombre"
git config --global user.email "tu@email.com"

# Editor de texto para mensajes de commit
git config --global core.editor "code --wait"   # VS Code
git config --global core.editor "vim"           # Vim
git config --global core.editor "nano"          # Nano

# Nombre de la rama principal por defecto
git config --global init.defaultBranch main

# Ver toda la configuración actual
git config --list

# Ver dónde está guardada la config
git config --list --show-origin

4. Los Tres Estados de Git

Para entender Git debes interiorizar que tus archivos pueden estar en tres estados:

Estado Zona Descripción
Modified Working Directory Archivos modificados pero aún no preparados para commit
Staged Staging Area (Index) Cambios marcados para incluir en el próximo commit
Committed Repository (.git) Datos guardados permanentemente en la base de datos local de Git
Working Directory  ──git add──▶  Staging Area  ──git commit──▶  Repository
      ◀──────────────────────────────────────────git checkout──────────

5. Primeros Pasos: Crear e Inicializar un Repositorio

Inicializar un repositorio nuevo

# Crear carpeta y entrar a ella
mkdir mi-proyecto
cd mi-proyecto

# Inicializar Git (crea la carpeta oculta .git)
git init

# Salida esperada:
# Initialized empty Git repository in /ruta/mi-proyecto/.git/

# Revisar el estado inicial
git status
# On branch main
# No commits yet
# nothing to commit

Clonar un repositorio existente

# Clonar desde GitHub (HTTPS)
git clone https://github.com/usuario/repositorio.git

# Clonar con SSH (recomendado para trabajo diario)
git clone git@github.com:usuario/repositorio.git

# Clonar en una carpeta con nombre personalizado
git clone https://github.com/usuario/repo.git mi-carpeta

# Clonar solo la rama main con historial de 1 commit (shallow clone — más rápido)
git clone --depth 1 https://github.com/usuario/repo.git

6. El Ciclo Diario: add → commit → push


git status — ¿qué está pasando?

git status

# Versión corta (muy útil en el día a día)
git status -s
# M  archivo-modificado.js    ← modificado y en staging
#  M archivo-solo-modificado  ← modificado, sin staging
# ?? archivo-nuevo.txt        ← sin seguimiento (untracked)

git add — pasar cambios al staging area

# Agregar un archivo específico
git add index.html

# Agregar varios archivos
git add src/app.js src/styles.css

# Agregar todos los archivos modificados y nuevos
git add .

# Agregar todos los archivos rastreados modificados (NO nuevos)
git add -u

# Agregar cambios de forma interactiva (te pregunta por cada bloque)
git add -p

git commit — guardar los cambios

# Commit con mensaje en la misma línea
git commit -m "feat: agregar formulario de contacto"

# Commit abriendo el editor para escribir un mensaje largo
git commit

# Agregar al staging y hacer commit en un solo paso (solo archivos rastreados)
git commit -am "fix: corregir validación de email"

# Modificar el último commit (antes de hacer push)
git commit --amend -m "Nuevo mensaje corregido"

# Agregar archivos olvidados al último commit
git add archivo-olvidado.js
git commit --amend --no-edit
Buenas prácticas para mensajes de commit:
Usa Conventional Commits: tipo(scope): descripción corta
Tipos: feat · fix · docs · style · refactor · test · chore

7. Ver el Historial: git log

# Historial completo
git log

# Compacto: una línea por commit
git log --oneline

# Con gráfico de ramas
git log --oneline --graph --all

# Últimos N commits
git log -5

# Ver qué archivos cambiaron en cada commit
git log --stat

# Buscar commits que tocan una cadena en el código
git log -S "función_buscar"

# Commits de un autor específico
git log --author="Andrés"

# Commits en un rango de fechas
git log --after="2024-01-01" --before="2024-12-31"

# Formato personalizado
git log --pretty=format:"%h — %an — %ar — %s"

8. Ver Diferencias: git diff

# Cambios en working directory vs staging
git diff

# Cambios en staging vs último commit
git diff --staged
git diff --cached   # equivalente

# Diferencia entre dos commits
git diff abc123 def456

# Diferencia entre dos ramas
git diff main..feature/login

# Solo ver qué archivos cambiaron (sin el contenido)
git diff --name-only

# Diferencia de un archivo específico
git diff src/app.js

9. Ramas (Branches): el superpoder de Git


Las ramas son copias ligeras del estado del repositorio. En Git, una rama es simplemente un puntero a un commit. Crearlas es instantáneo y barato.

# Ver todas las ramas locales
git branch

# Ver ramas locales y remotas
git branch -a

# Crear una rama nueva
git branch feature/nueva-funcionalidad

# Cambiar a una rama existente
git checkout feature/nueva-funcionalidad

# Crear rama y cambiar a ella en un solo paso (forma moderna)
git switch -c feature/login
git checkout -b feature/login   # equivalente clásico

# Renombrar la rama actual
git branch -m nuevo-nombre

# Eliminar una rama (solo si ya fue mergeada)
git branch -d feature/login

# Eliminar una rama forzado (sin importar si fue mergeada)
git branch -D feature/experimento

# Ver qué commit apunta cada rama
git branch -v

Diagrama conceptual de ramas

main:    A ── B ── C ──────────────── G  (merge commit)
                    \                /
feature:             D ── E ── F ───

10. Fusionar Ramas: git merge

# Primero, ir a la rama destino (normalmente main)
git switch main

# Fusionar la rama feature en main
git merge feature/login

# Merge con commit explícito (no fast-forward)
git merge --no-ff feature/login -m "Merge: agregar módulo de login"

# Cancelar un merge en progreso con conflictos
git merge --abort

Tipos de merge

  • Fast-forward: cuando no hay commits divergentes, Git simplemente mueve el puntero. No crea un merge commit. Historial limpio.
  • 3-way merge: cuando ambas ramas tienen commits nuevos, Git crea un commit de fusión con dos padres. Preserva la historia completa.

Resolver conflictos de merge

# Cuando hay conflicto, Git marca los archivos así:

<<<<<<< HEAD (tu rama actual)
const saludo = "Hola mundo";
=======
const saludo = "Hello world";
>>>>>>> feature/i18n (rama entrante)

# 1. Edita el archivo y elige qué código queda
# 2. Marca como resuelto
git add src/saludo.js

# 3. Completa el merge
git commit

# Ver qué archivos tienen conflictos
git status   # muestra "both modified"

# Herramienta visual de mergetool
git mergetool

11. Rebase: Reescribir la Historia

El rebase es una alternativa al merge que reaplica commits sobre una nueva base, produciendo un historial lineal y limpio.

# Estás en feature/login, quieres actualizarla con los últimos cambios de main
git switch feature/login
git rebase main

# Si hay conflictos durante rebase:
# 1. Resuelve los conflictos en los archivos
git add archivo-conflicto.js
git rebase --continue

# Cancelar el rebase y volver al estado anterior
git rebase --abort

# Rebase interactivo — editar los últimos 3 commits
git rebase -i HEAD~3

Rebase interactivo — comandos disponibles

# En el editor de rebase interactivo verás algo así:
pick a1b2c3d feat: agregar login
pick e4f5a6b fix: corregir typo
pick c7d8e9f refactor: limpiar código

# Comandos que puedes usar:
# pick   (p) — usar el commit tal cual
# reword (r) — cambiar el mensaje del commit
# edit   (e) — pausar para modificar el commit
# squash (s) — fusionar con el commit anterior
# fixup  (f) — como squash pero descarta el mensaje
# drop   (d) — eliminar el commit por completo
⚠ Regla de oro del rebase: Nunca hagas rebase de commits que ya están en una rama compartida (que otros han descargado). El rebase reescribe el historial y causará problemas a tus compañeros.

12. Remotos: Trabajar con GitHub

Colaboración en código remoto
# Ver los remotos configurados
git remote -v

# Agregar un remoto (por convención se llama "origin")
git remote add origin https://github.com/usuario/repo.git

# Cambiar la URL de un remoto
git remote set-url origin git@github.com:usuario/repo.git

# Eliminar un remoto
git remote remove origin

# Renombrar un remoto
git remote rename origin upstream

git fetch, pull y push

# fetch — descargar cambios remotos SIN fusionarlos
git fetch origin
git fetch --all   # desde todos los remotos

# pull — fetch + merge (o rebase)
git pull
git pull origin main
git pull --rebase   # recomendado: pull con rebase en lugar de merge

# push — subir commits al remoto
git push origin main
git push -u origin main   # primera vez: establece rama de seguimiento
git push                  # después ya funciona sin argumentos

# Subir una rama nueva al remoto
git push -u origin feature/login

# Eliminar una rama en el remoto
git push origin --delete feature/login

# Push forzado — CUIDADO: sobreescribe el historial remoto
git push --force-with-lease   # versión segura
git push --force              # versión peligrosa

13. Etiquetas: git tag

# Ver todas las etiquetas
git tag

# Crear una etiqueta ligera
git tag v1.0.0

# Crear una etiqueta anotada (recomendada — incluye autor, fecha y mensaje)
git tag -a v1.0.0 -m "Versión 1.0.0 — lanzamiento inicial"

# Etiquetar un commit anterior
git tag -a v0.9.0 abc123

# Ver detalles de una etiqueta
git show v1.0.0

# Subir etiquetas al remoto
git push origin v1.0.0
git push origin --tags   # todas las etiquetas

# Eliminar una etiqueta local
git tag -d v1.0.0

# Eliminar una etiqueta del remoto
git push origin --delete v1.0.0

14. Guardar Trabajo Temporal: git stash


Stash es como un cajón donde guardas cambios que no están listos para commit pero que tampoco quieres perder. Ideal cuando necesitas cambiar de rama urgentemente.

# Guardar cambios en el stash (working directory queda limpio)
git stash
git stash push -m "WIP: formulario de login a medias"

# Incluir archivos sin seguimiento (untracked)
git stash -u

# Ver la lista de stashes guardados
git stash list
# stash@{0}: WIP: formulario de login a medias
# stash@{1}: WIP on main: fix temporal

# Recuperar el stash más reciente (lo aplica y lo elimina de la lista)
git stash pop

# Recuperar un stash específico sin eliminarlo
git stash apply stash@{1}

# Ver el contenido de un stash
git stash show -p stash@{0}

# Eliminar un stash específico
git stash drop stash@{1}

# Limpiar todos los stashes
git stash clear

15. Deshacer Cambios

Uno de los poderes de Git es que casi nada se pierde para siempre. Aquí los principales comandos para deshacer:

Descartar cambios en el working directory

# Descartar cambios en un archivo (vuelve al estado del último commit)
git checkout -- src/app.js
git restore src/app.js   # forma moderna (Git 2.23+)

# Descartar TODOS los cambios del working directory
git restore .

Quitar archivos del staging area

# Sacar un archivo del staging (vuelve a modified)
git reset HEAD src/app.js
git restore --staged src/app.js   # forma moderna

git reset — mover el puntero HEAD

# --soft: mueve HEAD, pero deja staging y working directory intactos
git reset --soft HEAD~1   # deshace el último commit, cambios quedan en staging

# --mixed (por defecto): mueve HEAD y limpia staging, working directory intacto
git reset HEAD~1
git reset --mixed HEAD~1

# --hard: mueve HEAD, limpia staging Y working directory — DESTRUCTIVO
git reset --hard HEAD~1   # ⚠ CUIDADO: pierdes los cambios del working directory
git reset --hard origin/main   # ⚠ vuelve exactamente al estado del remoto

git revert — deshacer de forma segura

# Revert crea un NUEVO commit que deshace los cambios del commit indicado
# Es la forma segura de deshacer en ramas compartidas
git revert abc123
git revert HEAD   # revertir el último commit

# Revert sin abrir el editor de mensajes
git revert --no-edit HEAD

16. Cherry-pick: Copiar Commits Selectivos

# Aplicar un commit específico de otra rama en la rama actual
git cherry-pick abc123

# Cherry-pick sin crear commit automáticamente (queda en staging)
git cherry-pick -n abc123

# Aplicar un rango de commits
git cherry-pick abc123..def456

# Si hay conflicto:
git cherry-pick --continue
git cherry-pick --abort

17. Inspeccionar y Buscar

# git show — ver el detalle de un commit
git show abc123
git show HEAD
git show v1.0.0

# git blame — ver quién escribió cada línea de un archivo
git blame src/app.js
git blame -L 10,25 src/app.js   # solo líneas 10 a 25

# git grep — buscar texto en todos los archivos rastreados
git grep "TODO"
git grep -n "función_pagar"   # con número de línea

# git bisect — encontrar el commit que introdujo un bug (búsqueda binaria)
git bisect start
git bisect bad               # el estado actual está mal
git bisect good v1.0.0       # esta versión estaba bien
# Git hace checkout en commits intermedios; tú marcas good/bad
git bisect good
git bisect bad
git bisect reset             # terminar bisect

18. El archivo .gitignore


El archivo .gitignore le dice a Git qué archivos y carpetas debe ignorar completamente. Es fundamental incluirlo en cada proyecto.

# Ejemplo de .gitignore para un proyecto Java/Spring Boot

# Compilados
target/
*.class
*.jar

# Variables de entorno y secretos
.env
.env.local
application-secret.properties

# IDEs
.idea/
.vscode/
*.iml

# Logs
*.log
logs/

# Dependencias
node_modules/

# Sistema operativo
.DS_Store
Thumbs.db


# Sintaxis del .gitignore
*.log          # ignorar todos los archivos .log
!debug.log     # excepción: NO ignorar debug.log
/TODO          # solo ignorar /TODO en la raíz
build/         # ignorar el directorio build/
doc/**/*.txt   # ignorar .txt dentro de doc/ en cualquier nivel

# Si ya subiste por error un archivo, quítalo del seguimiento:
git rm --cached archivo-secreto.env
git commit -m "chore: remover archivo de credenciales del tracking"

19. Flujos de Trabajo en Equipos

Git Flow

Modelo clásico con ramas de larga duración:

  • main — código en producción
  • develop — integración de features
  • feature/* — nuevas funcionalidades
  • release/* — preparación de versión
  • hotfix/* — correcciones urgentes en producción

GitHub Flow (recomendado para la mayoría de equipos)

Modelo simplificado:

  1. La rama main siempre está desplegable
  2. Crea una rama descriptiva para cada tarea
  3. Haz commits frecuentemente
  4. Abre un Pull Request cuando quieras discutir o revisar
  5. Fusiona en main después de revisión y aprobación
# Flujo típico de trabajo en equipo con GitHub Flow:

# 1. Actualizar main
git switch main
git pull origin main

# 2. Crear rama para la tarea
git switch -c feature/JIRA-123-agregar-pago

# 3. Trabajar y hacer commits
git add .
git commit -m "feat: integrar pasarela de pago Stripe"

# 4. Subir la rama al remoto
git push -u origin feature/JIRA-123-agregar-pago

# 5. Abrir Pull Request en GitHub y pedir revisión

# 6. Después del merge, limpiar ramas
git switch main
git pull origin main
git branch -d feature/JIRA-123-agregar-pago

20. Git Hooks: Automatización de Calidad

# Los hooks viven en .git/hooks/
# Son scripts que se ejecutan en eventos específicos de Git

# Hooks más comunes:
# pre-commit      — antes de crear un commit (ejecutar tests, linter)
# commit-msg      — validar el formato del mensaje de commit
# pre-push        — antes de hacer push (ejecutar tests completos)
# post-checkout   — después de cambiar de rama

# Ejemplo: .git/hooks/pre-commit
#!/bin/bash
npm run lint
if [ $? -ne 0 ]; then
  echo "❌ Linting falló. Corrige los errores antes de hacer commit."
  exit 1
fi
echo "✓ Linting OK"

21. Comandos Avanzados y Tips de Productividad

Productividad con Git

git reflog — el historial de historial

# Ver todos los movimientos de HEAD (incluso commits borrados)
git reflog
# abc123 HEAD@{0}: commit: feat: nuevo feature
# def456 HEAD@{1}: reset --hard HEAD~3
# ghi789 HEAD@{2}: commit: commit borrado accidentalmente

# Recuperar un commit "perdido"
git checkout ghi789
git switch -c rama-recuperada

git worktree — trabajar en varias ramas a la vez

# Crear un segundo directorio de trabajo para otra rama
git worktree add ../mi-proyecto-hotfix hotfix/urgente

# Ver todos los worktrees
git worktree list

# Eliminar un worktree
git worktree remove ../mi-proyecto-hotfix

Alias útiles

# Configurar alias globales
git config --global alias.st status
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.lg "log --oneline --graph --all --decorate"
git config --global alias.undo "reset --soft HEAD~1"
git config --global alias.unstage "restore --staged"

# Ahora puedes usar:
git st          # en vez de git status
git lg          # log con gráfico
git undo        # deshacer último commit

Limpieza del repositorio

# Ver archivos sin seguimiento que serían borrados
git clean -n

# Borrar archivos sin seguimiento
git clean -f

# Borrar archivos y directorios sin seguimiento
git clean -fd

# Optimizar el repositorio local
git gc
git prune

22. Hoja de Referencia Rápida


Comando ¿Qué hace?
git init Inicializa un repo nuevo
git clone <url> Clona un repo remoto
git status Estado de archivos
git add . Stagear todos los cambios
git commit -m "" Crear un commit
git log --oneline Historial compacto
git branch -a Ver todas las ramas
git switch -c <rama> Crear y cambiar de rama
git merge <rama> Fusionar rama en la actual
git rebase <rama> Rebase sobre rama indicada
git stash Guardar cambios temporalmente
git stash pop Recuperar último stash
git pull --rebase Actualizar con rebase
git push -u origin <rama> Subir rama nueva al remoto
git reset --soft HEAD~1 Deshacer último commit (seguro)
git revert <hash> Revertir commit (histórico limpio)
git reflog Historial de movimientos de HEAD
git blame <archivo> Ver quién escribió cada línea
git bisect start Búsqueda binaria de bugs
git cherry-pick <hash> Copiar commit específico

Conclusión: Conviértete en un Maestro de Git

Maestría en control de versiones

Git es una de las herramientas que más retorno de inversión tiene en toda la carrera de un desarrollador. Una vez que lo dominas, tu forma de trabajar cambia para siempre: trabajas con confianza, colaboras sin miedo y tu código tiene una historia limpia y comprensible.

El camino recomendado es:

  1. Semana 1: Domina el ciclo básico: init → add → commit → push → pull
  2. Semana 2: Practica ramas: crea, fusiona, resuelve conflictos
  3. Semana 3: Aprende rebase interactivo y stash
  4. Mes 2: Contribuye a un proyecto open source con Pull Requests reales
  5. Siempre: Escribe mensajes de commit claros. Tu yo del futuro te lo agradecerá.
El mejor momento para aprender Git fue cuando empezaste a programar. El segundo mejor momento es ahora.