Las tres zonas
Un cambio pasa por tres lugares antes de quedar guardado en el historial:
Directorio de trabajo Staging (índice) Repositorio (.git)
┌──────────────────────┐ ┌────────────────────┐ ┌────────────────────┐
│ los archivos que se │ │ lo que entrará en │ │ historial de │
│ editan │ │ el próximo commit │ │ commits │
└──────────────────────┘ └────────────────────┘ └────────────────────┘
│ git add │ git commit │
└─────────────────────────▶└────────────────────────▶│
│◀──────────────── git restore / git switch ─────────│
| Zona | Qué contiene | Cómo se ve |
|---|---|---|
| Directorio de trabajo | Los archivos tal como están en disco | git status, git diff |
| Staging | La selección de cambios para el próximo commit | git diff --staged |
| Repositorio | Todos los commits ya guardados | git log |
El staging existe para elegir qué entra en cada commit. Se pueden editar cinco archivos y commitear solo dos.
Estados de un archivo
| Estado | Significa |
|---|---|
| untracked | Git no lo conoce todavía |
| modified | Cambió respecto al último commit, pero no está en staging |
| staged | Marcado para entrar en el próximo commit |
| committed | Guardado en el historial |
Qué es un commit
Un commit es una foto completa del proyecto en un momento, no una lista de diferencias. Guarda:
- el contenido de todos los archivos en ese momento,
- autor, fecha y mensaje,
- el identificador de su commit padre.
Cada commit se identifica por un hash (e69de29...) calculado a partir de su contenido. Cambiar cualquier cosa de un commit produce un hash distinto, y por eso el historial no se puede alterar sin que se note.
Ramas y HEAD
main
│
A ── B ── C
\
D ── E
│
feature ← HEAD
- Una rama es un puntero a un commit. Crear una rama no copia nada: solo crea un puntero nuevo.
- HEAD indica dónde se está: normalmente apunta a una rama. Al hacer commit, la rama a la que apunta HEAD avanza.
- Cambiar de rama mueve HEAD y actualiza los archivos del directorio de trabajo.
git log --oneline --graph --all # ver el grafo de commits y ramas
cat .git/HEAD # ref: refs/heads/main
Local y remoto
Todo lo anterior ocurre en el equipo propio. Un remoto (GitHub, por ejemplo) es otra copia del repositorio con la que se sincroniza de forma explícita con git fetch, git pull y git push. Nada sale del equipo hasta hacer push.