Ana tiene su repositorio y Bruno tiene su clon. A partir de aquí, los dos hacen exactamente lo mismo cada día, decenas de veces: editan ficheros, deciden qué cambios agrupar y los registran en el historial. Ese ciclo de tres pasos —editar, preparar, confirmar— es el latido de Git. Todo lo demás del curso (ramas, fusiones, rebase, remotos) se construye encima.
En el módulo 1 aprendiste la teoría: las tres zonas (directorio de trabajo, área de preparación y repositorio) y los tres estados (modificado, preparado, confirmado). En esta lección esa teoría se pone en movimiento. Vamos a ver cómo un fichero viaja de una zona a otra, qué estados atraviesa desde que Git no lo conoce hasta que queda confirmado, y cómo git status te dice en todo momento exactamente dónde estás.
El objetivo es que, al terminar, puedas mirar la salida de git status en cualquier repositorio del mundo y saber en un segundo qué está pasando y cuál es el siguiente comando razonable.
Contenido
- El ciclo de tres pasos
- Las tres zonas en movimiento
- El ciclo de vida de un fichero
git status: la brújulagit status --short: la forma abreviada y su tabla de códigos- Ficheros que no quieres versionar:
.gitignoreen dos minutos - Una sesión de trabajo completa de Ana, narrada
- El ciclo en la práctica diaria
- El ciclo de tres pasos
El flujo de trabajo básico de Git tiene esta forma:
graph LR
E["1 · EDITAR<br/>Modificas ficheros<br/>en tu carpeta"] --> P["2 · PREPARAR<br/>git add<br/>Eliges qué entra"]
P --> C["3 · CONFIRMAR<br/>git commit<br/>Se registra para siempre"]
C -.->|vuelta a empezar| E
Tres pasos, dos comandos. Lo que desconcierta al principio es el paso intermedio: ¿por qué no basta con "guardar los cambios"? ¿Para qué existe el área de preparación?
La respuesta es que separa dos decisiones distintas:
- Editar responde a "¿qué he cambiado?". Es trabajo.
- Preparar responde a "¿qué de lo que he cambiado forma una unidad con sentido?". Es criterio.
Imagina que Ana pasa la mañana arreglando un fallo en app.js y, de paso, corrige una falta de ortografía en README.md y ajusta un color en estilos.css. Son tres cosas sin relación entre sí. Sin área de preparación, tendría dos opciones malas: meterlo todo en una confirmación revuelta, o ir deshaciendo cambios a mano para confirmarlos por separado. Con el área de preparación, elige: prepara solo app.js, confirma, prepara README.md, confirma, y así.
El resultado es un historial donde cada confirmación cuenta una sola cosa. Cuando dentro de seis meses alguien busque por qué se rompió el borrado de tareas, encontrará una confirmación que habla exactamente de eso y no de tres asuntos mezclados.
Esta idea —el commit atómico— es tan importante que la desarrollamos a fondo en la siguiente lección, Preparando y Confirmando Cambios.
- Las tres zonas en movimiento
Recuperemos el esquema de Terminología Básica de Git, esta vez con los comandos que mueven la información de una zona a otra:
graph LR
WT["DIRECTORIO<br/>DE TRABAJO<br/>Tus ficheros<br/>en el disco"]
IDX["ÁREA DE<br/>PREPARACIÓN<br/>.git/index<br/>El borrador del<br/>próximo commit"]
REPO["REPOSITORIO<br/>.git/objects<br/>El historial<br/>permanente"]
WT -->|git add| IDX
IDX -->|git commit| REPO
IDX -->|git restore --staged| WT
REPO -->|git checkout / git restore --source| WT
Tres reglas que conviene tener grabadas:
- Solo se confirma lo que está preparado.
git commitno mira el directorio de trabajo: fotografía el área de preparación. Un cambio que no hayas preparado no entra, por muy guardado que esté en el disco. - El área de preparación es un estado, no una cola. No es una lista de comandos pendientes; es una versión completa del proyecto. Contiene el contenido íntegro de cada fichero, no "las líneas que has añadido".
- Las tres zonas pueden tener contenidos distintos del mismo fichero a la vez. Es la fuente de confusión número uno de los principiantes, y también la fuente del poder de Git. Lo veremos en acción en la sesión narrada.
- El ciclo de vida de un fichero
Cada fichero de tu carpeta está, en cada momento, en uno de cuatro estados. Este diagrama los recoge todos y muestra qué comando produce cada transición:
stateDiagram-v2
[*] --> SinSeguimiento: creas el fichero
SinSeguimiento --> Preparado: git add
Preparado --> SinModificar: git commit
SinModificar --> Modificado: editas el fichero
Modificado --> Preparado: git add
Preparado --> Modificado: editas otra vez
Preparado --> SinSeguimiento: git rm --cached
Modificado --> SinModificar: git restore
SinModificar --> [*]: git rm
SinSeguimiento: Sin seguimiento (untracked)
SinModificar: Sin modificar (unmodified)
Modificado: Modificado (modified)
Preparado: Preparado (staged)
Veamos los cuatro estados uno a uno:
| Estado | En inglés | Qué significa | Cómo lo ves en git status |
|---|---|---|---|
| Sin seguimiento | untracked | Git ve el fichero pero nunca lo ha registrado. No forma parte del proyecto | En la sección Untracked files |
| Sin modificar | unmodified | Idéntico a la última confirmación. No hay nada que hacer con él | No aparece: Git solo informa de lo que cambia |
| Modificado | modified | Ha cambiado respecto a la última confirmación, pero no se ha preparado | En Changes not staged for commit |
| Preparado | staged | Su versión actual entrará en la próxima confirmación | En Changes to be committed |
Hay una distinción de fondo que conviene fijar: rastreado frente a no rastreado. Un fichero está rastreado si aparece en la última confirmación o en el área de preparación; es decir, si Git lo conoce. Los tres estados "sin modificar", "modificado" y "preparado" son variantes de rastreado. "Sin seguimiento" es la única categoría de fuera.
Esta distinción importa porque muchos comandos actúan solo sobre ficheros rastreados. Por ejemplo, git commit -a prepara automáticamente los ficheros modificados, pero no los que están sin seguimiento; hay que añadirlos a mano al menos una primera vez.
Un detalle clave: un fichero puede estar en dos estados a la vez
Fíjate en la transición Preparado --> Modificado del diagrama. Es real y ocurre constantemente:
- Ana modifica
app.jsy lo prepara congit add app.js. El área de preparación guarda esa versión. - Ana sigue trabajando y vuelve a tocar
app.js. Ahora el disco tiene una versión más nueva que el área de preparación.
Resultado: app.js aparece en las dos secciones de git status, la de preparados y la de no preparados. No es un error ni una anomalía: hay dos versiones distintas guardadas en dos zonas distintas, y si Ana confirmara ahora, entraría la preparada (la más antigua), no la del disco.
git status: la brújula
git status: la brújulaSi tuvieras que quedarte con un solo comando de Git, sería este. No modifica nada, es instantáneo y responde siempre a las mismas cuatro preguntas: en qué rama estás, cómo estás respecto al remoto, qué hay preparado y qué hay pendiente.
Vamos a leer una salida completa, con todos los casos a la vez:
On branch main Your branch is up to date with 'origin/main'. Changes to be committed: (use "git restore --staged <file>..." to unstage) modified: estilos.css new file: .gitignore 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: app.js deleted: antiguo.js Untracked files: (use "git add <file>..." to include in what will be committed) notas.txt
Diseccionémoslo bloque a bloque:
Cabecera.
On branch main: la rama actual. Es lo primero que hay que mirar; equivocarse de rama es un clásico.Your branch is up to date with 'origin/main': comparación con la rama de seguimiento del remoto. Solo aparece si existe un remoto configurado, como en el clon de Bruno. Puede decir tambiénahead by N commitsobehind by N commits. Lo desarrollaremos en el módulo 4.
Changes to be committed — el área de preparación. Todo lo que aparezca aquí entrará en el próximo git commit. Cada línea lleva un verbo que indica el tipo de cambio: modified, new file, deleted, renamed.
Changes not staged for commit — cambios en el directorio de trabajo sobre ficheros que Git ya rastrea, pero que no entrarán en el próximo commit. Ojo: aquí solo aparecen ficheros rastreados.
Untracked files — ficheros que Git ve por primera vez. Nunca entrarán en ninguna confirmación hasta que hagas git add explícitamente.
Las sugerencias entre paréntesis. Git te dice, en cada sección, cómo avanzar y cómo retroceder. Merece la pena leerlas: son la mejor documentación en línea que existe.
Las salidas que verás más a menudo
Todo confirmado, nada pendiente. Las tres zonas coinciden. Es el estado ideal para cambiar de tarea.
On branch main Untracked files: (use "git add <file>..." to include in what will be committed) notas.txt nothing added to commit but untracked files present (use "git add" to track)
No hay nada preparado. Si hicieras git commit ahora, Git se negaría porque no habría nada que confirmar.
On branch main Changes not staged for commit: (use "git add <file>..." to update what will be committed) modified: app.js no changes added to commit (use "git add" and/or "git commit -a")
Has trabajado, pero no has preparado nada. La última línea es la advertencia: git commit a secas no haría nada.
git status --short: la forma abreviada y su tabla de códigos
git status --short: la forma abreviada y su tabla de códigosLa salida larga es excelente para aprender, pero cansa cuando la consultas cuarenta veces al día. La forma corta cabe en una pantalla:
La clave está en que hay dos columnas antes del nombre del fichero, y significan cosas distintas:
- Columna 1 (izquierda): el estado en el ÁREA DE PREPARACIÓN.
- Columna 2 (derecha): el estado en el DIRECTORIO DE TRABAJO.
Entender esto convierte una salida críptica en información precisa. Los códigos posibles:
| Código | Nombre | Significado |
|---|---|---|
(espacio) |
sin cambios | Nada que reportar en esa zona |
M |
modified | Modificado |
A |
added | Añadido (fichero nuevo, ya preparado) |
D |
deleted | Borrado |
R |
renamed | Renombrado |
C |
copied | Copiado |
U |
updated but unmerged | Conflicto sin resolver (lo verás en el módulo 3) |
? |
untracked | Sin seguimiento (aparece como ??) |
! |
ignored | Ignorado (solo con --ignored) |
Y ahora las combinaciones que realmente aparecen en el día a día:
| Salida | Columna 1 | Columna 2 | Interpretación |
|---|---|---|---|
M |
M |
|
Modificado y preparado. Entrará tal cual |
M |
|
M |
Modificado sin preparar. No entrará |
MM |
M |
M |
Preparado y vuelto a modificar después. Entrará la versión preparada |
A |
A |
|
Fichero nuevo, ya preparado |
AM |
A |
M |
Añadido y modificado después de añadirlo |
D |
D |
|
Borrado, y el borrado está preparado |
D |
|
D |
Borrado del disco, pero sin preparar el borrado |
R |
R |
|
Renombrado, preparado |
?? |
— | — | Sin seguimiento |
UU |
U |
U |
Conflicto: ambos lados modificaron el fichero |
Aplicado al ejemplo anterior:
M estilos.css→ modificado y preparado. Entrará en el commit.A .gitignore→ nuevo y preparado. Entrará.M app.js→ modificado pero sin preparar. No entrará. Fíjate en el espacio inicial: es significativo.D antiguo.js→ borrado del disco, sin preparar. El commit seguiría incluyendo el fichero.?? notas.txt→ sin seguimiento. No entrará.
Truco de lectura. Coloca el dedo sobre la primera columna: lo que queda tapado es "lo que hay en el disco". Descúbrela: lo que ves ahí es "lo que va a entrar en el commit".
Una variante muy útil añade la información de rama:
La primera línea resume rama actual, rama de seguimiento y divergencia. Con -sb tienes en cinco líneas todo lo que la salida larga cuenta en veinticinco.
- Ficheros que no quieres versionar:
.gitignore en dos minutos
.gitignore en dos minutosHay un problema práctico con Untracked files: muchas carpetas de proyecto acumulan ficheros que nunca deben versionarse. Dependencias instaladas, resultados de compilación, ficheros temporales del editor, credenciales, ficheros del sistema operativo… Si aparecen todos en cada git status, la señal se pierde entre el ruido y acabas ignorando la salida del comando, que es justo lo que no quieres.
La solución es un fichero llamado .gitignore en la raíz del proyecto, con un patrón por línea:
# Dependencias node_modules/ # Credenciales .env # Registros y temporales *.log notas.txt # Ficheros del sistema .DS_Store Thumbs.db
Los ficheros que coincidan con esos patrones desaparecen de git status y no se pueden añadir por accidente con git add .. El propio .gitignore sí se versiona: es parte del proyecto y debe ser igual para todo el equipo, lo cual resuelve de paso un conflicto histórico entre los tres sistemas operativos de Ana, Bruno y Carla (.DS_Store en macOS, Thumbs.db en Windows).
Dos matices que evitan la frustración más común:
.gitignoresolo afecta a ficheros sin seguimiento. Si un fichero ya está rastreado, añadirlo al.gitignoreno lo saca del proyecto: hay que quitarlo del índice explícitamente, algo que veremos en Preparando y Confirmando Cambios.- Escríbelo pronto, idealmente antes del primer
git add, como vimos en Creando un Repositorio.
Con esto tienes lo necesario para trabajar. Los patrones avanzados, las negaciones con !, los .gitignore por subdirectorio, el fichero global y .git/info/exclude se tratan a fondo en Ignorando Archivos con .gitignore.
- Una sesión de trabajo completa de Ana, narrada
Vamos a seguir a Ana durante una tarde entera. Es martes y quiere añadir un contador de tareas pendientes a gestor-tareas. Punto de partida:
Todo limpio: las tres zonas coinciden con la última confirmación. Es el punto de partida correcto para empezar algo nuevo.
17:05 — Edita tres ficheros
Añade el elemento del contador en index.html:
Le da estilo en estilos.css:
Y añade la lógica en app.js:
function actualizarContador() {
const pendientes = tareas.filter(function (t) { return !t.hecha; }).length;
document.querySelector('#contador').textContent = pendientes + ' tareas pendientes';
}De paso, arranca el proyecto para probarlo, lo que genera un fichero de registro, y abre un bloc de notas con ideas sueltas.
17:40 — Primera consulta
On branch main 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: app.js modified: estilos.css modified: index.html Untracked files: (use "git add <file>..." to include in what will be committed) depuracion.log notas.txt no changes added to commit (use "git add" and/or "git commit -a")
Cinco entradas: tres ficheros del proyecto modificados y dos ficheros nuevos que no quiere versionar. La última línea le recuerda que, tal como está, git commit no haría nada.
17:42 — Quita el ruido
Antes de preparar nada, escribe el .gitignore:
depuracion.log y notas.txt han desaparecido. Ahora la salida solo contiene señal. Fíjate en las tres líneas que empiezan por espacio: columna 1 vacía significa que nada de eso entraría todavía en un commit.
17:45 — Prepara
La M y la A se han desplazado a la primera columna. Los cuatro ficheros están preparados. En la forma larga:
On branch main Changes to be committed: (use "git restore --staged <file>..." to unstage) new file: .gitignore modified: app.js modified: estilos.css modified: index.html
Ha desaparecido la sección de "no preparados": no queda nada pendiente en el directorio de trabajo.
17:52 — Se da cuenta de una errata
Probando la página, Ana ve que el contador dice "1 tareas pendientes". Corrige app.js para que el singular funcione:
function actualizarContador() {
const pendientes = tareas.filter(function (t) { return !t.hecha; }).length;
const texto = pendientes === 1 ? '1 tarea pendiente' : pendientes + ' tareas pendientes';
document.querySelector('#contador').textContent = texto;
}Y consulta de nuevo:
Ahí está el caso interesante: MM app.js. El fichero aparece con M en las dos columnas. Significa exactamente esto:
- Columna 1 (
M): hay una versión deapp.jspreparada — la de las 17:45, sin la corrección del singular. - Columna 2 (
M): el fichero del disco es distinto de esa versión preparada — tiene la corrección.
En la forma larga se ve todavía más claro, porque el mismo fichero sale dos veces:
On branch main Changes to be committed: new file: .gitignore modified: app.js modified: estilos.css modified: index.html Changes not staged for commit: modified: app.js
Si Ana confirmara ahora, entraría la versión con la errata. Es la trampa clásica de Git y la razón por la que conviene mirar git status justo antes de confirmar.
17:53 — Vuelve a preparar
La segunda columna de app.js vuelve a estar vacía. Ahora la versión preparada es la buena.
17:55 — Confirma
[main 2f6a3c8] Añadir contador de tareas pendientes 4 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 .gitignore
Vuelta al punto de partida. Las tres zonas coinciden otra vez, ahora sobre una confirmación nueva. Y comprobemos que los ficheros ignorados siguen ahí, simplemente invisibles para Git:
Están en el disco, marcados como ignorados. Git los ve y decide, deliberadamente, no molestarte con ellos.
El recorrido en un diagrama
sequenceDiagram
participant D as Directorio<br/>de trabajo
participant I as Área de<br/>preparación
participant R as Repositorio
Note over D,R: 17:05 — Ana edita 3 ficheros
Note over D: app.js, estilos.css, index.html modificados
Note over D,R: 17:42 — Escribe .gitignore
Note over D: depuracion.log y notas.txt desaparecen de status
D->>I: 17:45 git add (4 ficheros)
Note over D,R: 17:52 — Corrige una errata en app.js
Note over D,I: app.js aparece como MM
D->>I: 17:53 git add app.js
I->>R: 17:55 git commit -m "Añadir contador..."
Note over D,R: working tree clean
- El ciclo en la práctica diaria
Con el flujo interiorizado, el día a día se reduce a un puñado de hábitos:
El bucle mínimo, que ejecutarás miles de veces:
git status # ¿dónde estoy?
# ... editar ...
git add <ficheros> # ¿qué agrupo?
git status # ¿es exactamente eso lo que va a entrar?
git commit -m "..." # registrarCuatro hábitos que marcan la diferencia:
git statusantes de empezar. Saber si arrancas de un árbol limpio o si te dejaste algo a medias ayer evita mezclar dos tareas en una confirmación.git statusantes de confirmar. Es el único momento en que puedes detectar unMMo un fichero olvidado. Cuesta un segundo.- Confirma pronto y a menudo. Una confirmación no es una entrega ni una publicación: es un punto de guardado. Un historial de veinte confirmaciones pequeñas es infinitamente más útil que uno de dos confirmaciones gigantes.
- Termina el día con el árbol limpio siempre que puedas. Si no es posible, al menos deja anotado en qué estabas.
Qué hacer cuando el bucle se rompe. Estas son las situaciones más frecuentes y su salida; todas se desarrollan en la siguiente lección:
| Situación | Comando |
|---|---|
| Preparé un fichero que no quería | git restore --staged <fichero> |
| Quiero descartar mis cambios de un fichero | git restore <fichero> |
| Me equivoqué en el mensaje del último commit | git commit --amend |
| Quiero ver qué he cambiado exactamente | git diff (lección 02-05) |
| Quiero ver qué se ha hecho hasta ahora | git log (lección 02-06) |
Errores Comunes y Consejos
- Confirmar sin mirar
git status. El casoMM—un fichero preparado y luego vuelto a modificar— hace que entre en el historial una versión que no es la que tienes delante. Un vistazo al estado antes de confirmar lo evita. - Creer que
git add"guarda" el fichero.git addno guarda nada de forma permanente: copia el contenido actual al área de preparación. Si sigues editando, esa copia se queda vieja. - Olvidar que
git commit -ano incluye ficheros sin seguimiento. La opción-aprepara automáticamente los ficheros rastreados modificados o borrados. Un fichero nuevo hay que añadirlo congit addal menos una vez. - Ignorar la sección
Untracked files. Es donde se esconde el fichero nuevo que olvidaste añadir y por el que el proyecto no compila en la máquina de tu compañero. - Malinterpretar las dos columnas de
--short.M(espacio y eme) yM(eme y espacio) significan cosas opuestas. Si dudas, usa la forma larga. - Trabajar con
git statuslleno de ruido. Si tienes cuarenta ficheros sin seguimiento que nunca vas a versionar, escribe el.gitignore. Unstatuslegible es una herramienta; uno ilegible es un estorbo. - Añadir
.gitignoredemasiado tarde. Si el fichero ya está rastreado, ignorarlo no tiene efecto. Hay que sacarlo del índice primero. - Consejo: define un alias corto para el estado, ya que lo usarás constantemente:
git config --global alias.s "status -sb". Después basta congit s. Los alias se tratan en Git Log y Alias. - Consejo: si
git statustarda mucho en un proyecto grande, suele ser síntoma de que hay demasiados ficheros sin seguimiento (dependencias, artefactos de compilación). Un buen.gitignorelo arregla.
Ejercicios
Ejercicio 1: Leer el estado sin ejecutar Git
Un repositorio muestra esta salida:
## main...origin/main [ahead 1] A config.json MM app.js M estilos.css D antiguo.css D index.html ?? borrador.txt R README.md -> LEEME.md
Responde razonadamente:
- ¿Qué ficheros entrarán en el próximo
git commit(sin usar-a) y con qué cambio? - ¿Qué le pasa a
app.js? Si se confirma ahora, ¿qué versión queda registrada? index.htmlse ha borrado del disco. ¿Desaparecerá del proyecto al confirmar?- ¿Cuántas confirmaciones tiene esta rama por delante del remoto?
- Escribe la secuencia de comandos que dejaría el estado listo para que todo lo borrado, modificado y renombrado entre en el commit, salvo
borrador.txt, que no debe versionarse nunca.
Ejercicio 2: Reproducir el caso MM
Crea un repositorio de prueba y provoca deliberadamente la situación en la que se confirma una versión antigua de un fichero:
- Crea un repositorio con un fichero
app.jsque contenga la líneaconst version = 1;y confírmalo. - Cambia la línea a
const version = 2;y prepara el cambio. - Sin confirmar, cambia la línea a
const version = 3;. - Comprueba el estado en forma corta y larga.
- Confirma sin volver a preparar.
- Averigua con comandos qué versión ha quedado registrada en el historial y cuál sigue en tu disco.
- Arregla la situación para que el historial refleje la versión 3.
Ejercicio 3: Limpiar el ruido de un proyecto heredado
Te pasan un proyecto en el que git status muestra esto:
On branch main Untracked files: .env .vscode/settings.json build/index.js build/estilos.css dist/paquete.zip informe.log node_modules/ (miles de ficheros) src/nuevoModulo.js temp~
Solo src/nuevoModulo.js debe versionarse. Escribe:
- El
.gitignoreque dejagit statusmostrando únicamente ese fichero. - Los comandos para verificar que funciona, incluida una comprobación explícita de que
.envestá siendo ignorado y por qué regla. - La secuencia para confirmar el
.gitignorey el módulo nuevo en dos confirmaciones separadas, y una justificación de por qué separarlas.
Soluciones
Solución al Ejercicio 1
1. Qué entrará en el commit. Todo lo que tenga algo distinto de un espacio en la primera columna:
| Fichero | Código | Entra como |
|---|---|---|
config.json |
A |
Fichero nuevo |
app.js |
MM |
Modificado (la versión preparada) |
antiguo.css |
D |
Borrado |
README.md -> LEEME.md |
R |
Renombrado |
No entran estilos.css ( M), index.html ( D) ni borrador.txt (??), porque su primera columna está vacía o son ficheros desconocidos para Git.
2. app.js es el caso MM: hay una versión preparada y, encima, el fichero del disco es distinto de ella. Al confirmar quedará registrada la versión preparada, no la que hay en el disco. La diferencia entre ambas se quedará como cambio pendiente después del commit.
3. index.html no desaparecerá. El código D indica que el borrado está en el disco pero no preparado. La confirmación seguirá conteniendo el fichero, así que quien clone el repositorio lo recibirá. Es un error habitual: borrar con el explorador de ficheros y olvidar registrar el borrado.
4. Una confirmación por delante, según [ahead 1]: hay un commit local que el remoto todavía no tiene.
5. La secuencia:
# 1. Excluir el borrador para que no se cuele nunca
echo "borrador.txt" >> .gitignore
# 2. Preparar todo lo pendiente de los ficheros rastreados,
# incluidos los borrados
git add -u
# 3. Preparar el .gitignore, que es un fichero nuevo
git add .gitignore
# 4. Verificar antes de confirmar
git status -sA .gitignore A config.json M app.js M estilos.css D antiguo.css D index.html R README.md -> LEEME.md
La segunda columna está vacía en todas las líneas y borrador.txt ha desaparecido: exactamente lo pedido. La opción -u de git add es la clave —prepara modificaciones y borrados de ficheros ya rastreados, sin tocar los nuevos— y la estudiaremos en detalle en la lección siguiente.
Solución al Ejercicio 2
Pasos 1 a 3:
mkdir -p ~/practica/estados && cd ~/practica/estados
git init
echo "const version = 1;" > app.js
git add app.js
git commit -m "Versión inicial"
echo "const version = 2;" > app.js
git add app.js
echo "const version = 3;" > app.jsPaso 4 — el estado:
On branch main Changes to be committed: modified: app.js Changes not staged for commit: modified: app.js
El mismo fichero aparece dos veces. La forma larga lo hace evidente; la corta lo condensa en MM.
Paso 5 — confirmar:
Paso 6 — qué ha quedado dónde:
# Lo que hay en el historial
git show HEAD:app.js
# → const version = 2;
# Lo que hay en tu disco
cat app.js
# → const version = 3;
# Y sigue habiendo trabajo pendiente
git status -s
# → M app.jsConfirmado: ha entrado la versión 2, la que estaba preparada. La 3 sigue en el directorio de trabajo, todavía sin registrar. Este es el efecto exacto que produce ignorar un MM.
Paso 7 — arreglarlo:
Es la solución más segura: una confirmación nueva encima. (Existe otra alternativa, git commit --amend, que corrige la confirmación anterior en lugar de añadir una nueva; se estudia en la lección siguiente y conviene usarla solo sobre confirmaciones que aún no se han compartido, porque reescribe el historial.)
Solución al Ejercicio 3
1. El .gitignore:
# Dependencias node_modules/ # Artefactos de compilación build/ dist/ # Configuración local del editor .vscode/ # Credenciales .env # Registros y temporales *.log *~
2. Verificación:
Exactamente dos entradas: el propio .gitignore y el fichero que sí queremos versionar.
Para comprobar por qué se ignora un fichero concreto existe un comando específico:
La salida indica el fichero de reglas, el número de línea, el patrón que coincide y el fichero evaluado. Es la herramienta correcta para depurar un .gitignore que "no funciona": si el comando no devuelve nada, es que ninguna regla se aplica.
Y una comprobación adicional que da tranquilidad:
3. Dos confirmaciones separadas:
git add .gitignore
git commit -m "Añadir .gitignore con dependencias, artefactos y credenciales"
git add src/nuevoModulo.js
git commit -m "Añadir el módulo de generación de informes"Por qué separarlas. Son dos cambios sin ninguna relación: uno configura qué versiona el proyecto y el otro añade funcionalidad. Separarlos tiene ventajas concretas:
- Cada confirmación puede describirse con una sola frase honesta.
- Si mañana hay que revisar por qué se ignora
dist/, se encuentra una confirmación que habla solo de eso. - Si el módulo nuevo resulta ser un error y hay que deshacerlo, se deshace sin arrastrar el
.gitignore.
Es la idea de commit atómico, que desarrollamos justo en la siguiente lección.
Conclusión
Ya tienes el ciclo completo. Recapitulando:
- El flujo básico son tres pasos —editar, preparar, confirmar— y dos comandos,
git addygit commit. El paso intermedio existe para separar el trabajo (qué he cambiado) del criterio (qué forma una unidad con sentido). - Las tres zonas se mueven con comandos concretos:
git addlleva del directorio de trabajo al área de preparación,git commitdel área al repositorio, ygit restoredeshace en ambas direcciones. - Un fichero atraviesa cuatro estados: sin seguimiento, sin modificar, modificado y preparado. Solo los tres últimos corresponden a ficheros rastreados, y muchos comandos actúan únicamente sobre esos.
- Un mismo fichero puede estar en dos estados a la vez (el caso
MM), y si no lo detectas confirmarás una versión que no es la que tienes delante. git statuses la brújula. En su forma larga enseña; en su forma corta (-s,-sb) informa de un vistazo, con dos columnas que separan el área de preparación del directorio de trabajo..gitignoremantiene la señal limpia excluyendo lo que nunca debe versionarse, pero solo actúa sobre ficheros sin seguimiento.
Con esto ya puedes trabajar. Lo que falta es precisión: hasta ahora hemos preparado ficheros enteros con git add <fichero>, y eso no siempre es lo que quieres. ¿Y si en un mismo fichero tienes dos cambios que pertenecen a confirmaciones distintas? ¿Cómo quitas algo del área de preparación? ¿Cómo se borra o se renombra un fichero dentro de Git? ¿Y si te equivocas en el mensaje del commit que acabas de hacer?
De todo eso trata la siguiente lección, Preparando y Confirmando Cambios: git add a fondo con sus opciones -A, -u y . —una fuente clásica de confusión— y el modo interactivo por fragmentos, cómo deshacer preparaciones con git restore, git mv y git rm, y todas las variantes de git commit, incluida --amend para corregir la última confirmación.
Dominando Git: De Principiante a Avanzado
Módulo 1: Introducción a Git
- ¿Qué es Git?
- Instalando Git
- Terminología Básica de Git
- El Modelo de Datos de Git
- Configurando Git
- Configuración Inicial
Módulo 2: Operaciones Básicas de Git
- Creando un Repositorio
- Clonando un Repositorio
- Flujo de Trabajo Básico de Git
- Preparando y Confirmando Cambios
- Inspeccionando Cambios con git diff
- Visualizando el Historial de Confirmaciones
Módulo 3: Ramas y Fusión
- Entendiendo las Ramas
- Creando y Cambiando Ramas
- Fusionando Ramas
- Estrategias de Fusión
- Resolviendo Conflictos de Fusión
- Gestión de Ramas
Módulo 4: Trabajando con Repositorios Remotos
- Entendiendo los Repositorios Remotos
- Agregando un Repositorio Remoto
- Autenticación con Repositorios Remotos
- Obteniendo y Extrayendo Cambios
- Enviando Cambios
- Rastreando Ramas
Módulo 5: Operaciones Avanzadas de Git
- Rebase
- Rebase Interactivo
- Cherry-Picking de Confirmaciones
- Guardando Cambios Temporales
- Etiquetando Confirmaciones
- Revirtiendo Confirmaciones
Módulo 6: Herramientas y Técnicas de Git
- Usando Git Hooks
- Git Bisect
- Git Blame
- Git Log y Alias
- Submódulos de Git
- Múltiples Copias de Trabajo con git worktree
Módulo 7: Estrategias de Colaboración y Flujo de Trabajo
- Forks y Pull Requests
- Revisiones de Código con Git
- Flujo de Trabajo Git Flow
- GitHub Flow
- Trunk Based Development
- Integración Continua con Git
Módulo 8: Mejores Prácticas y Consejos de Git
- Escribiendo Buenos Mensajes de Confirmación
- Manteniendo un Historial Limpio
- Ignorando Archivos con .gitignore
- Atributos de Fichero con .gitattributes
- Mejores Prácticas de Seguridad
- Consejos de Rendimiento
Módulo 9: Solución de Problemas y Depuración
- Problemas Comunes de Git
- Deshaciendo Cambios
- Resolviendo Divergencias con el Remoto
- Recuperando Confirmaciones Perdidas
- Tratando con Repositorios Corruptos
- Técnicas Avanzadas de Depuración
