Guía

git add y git commit: cómo guardar cambios correctamente

Actualizado: · Skillaria.Top

Guardar cambios en Git son dos pasos: git add añade al índice (staging area) las modificaciones que quiere incluir, y git commit -m "mensaje" las registra en el historial como una sola instantánea. git status muestra qué ha cambiado y qué está ya preparado. El último commit se puede corregir con git commit --amend.

Git no tiene un botón de «guardar». Los cambios se fijan en dos pasos: primero git add selecciona qué modificaciones entrarán en la próxima instantánea, y después git commit registra esa instantánea en el historial. La zona intermedia entre ambos se llama índice o staging area. Mucha gente tarda años en entenderla, y es precisamente lo que hace que los commits tengan sentido.

Los tres estados de un archivo: directorio de trabajo, índice, historial

Cualquier cambio recorre tres áreas:

  1. Directorio de trabajo: usted edita el archivo en el editor.
  2. Índice (stage): git add coloca la versión actual del archivo en el borrador del próximo commit.
  3. Historial: git commit convierte el contenido del índice en un commit con autor, fecha y mensaje.

Una analogía útil es un paquete. El directorio de trabajo es la habitación con sus cosas, el índice es la caja abierta donde mete lo que quiere enviar, y el commit es el paquete cerrado y etiquetado. Usted decide qué va en la caja y no está obligado a enviarlo todo a la vez.

Para qué sirve el índice

Imagine que en una hora ha corregido un bug en la autenticación, de paso ha arreglado una errata en el README y ha empezado una funcionalidad nueva. Sin índice, todo acabaría en un único commit «varios». Con el índice hace tres commits separados, cada uno fácil de entender, revisar en el code review y, si hace falta, revertir sin tocar lo demás.

git status: qué ha cambiado y qué está preparado

Antes de cada add y commit conviene mirar git status. Es el comando más seguro de Git: no modifica nada.

$ git status
On branch main
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   src/auth.js

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:   README.md

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        src/profile.js
  • Changes to be committed: ya está en el índice y entrará en el commit;
  • Changes not staged: modificado, pero no añadido;
  • Untracked files: archivos nuevos que Git todavía no conoce.

El formato corto es más cómodo cuando hay muchos archivos:

$ git status -s
M  src/auth.js
 M README.md
?? src/profile.js

La primera columna es el estado en el índice; la segunda, en el directorio de trabajo. Una M a la izquierda significa «modificado y añadido»; a la derecha, «modificado, sin añadir»; ?? indica un archivo sin rastrear.

git add: cómo añadir cambios al índice

ComandoQué añade
git add file.jsUn archivo concreto
git add src/Todo lo modificado en la carpeta
git add .Todos los cambios de la carpeta actual y sus subcarpetas, incluidos archivos nuevos y eliminados
git add -ATodos los cambios de todo el repositorio
git add -uSolo archivos ya rastreados; no toca los nuevos
git add -pDe forma interactiva, por fragmentos (hunks)
git add '*.css'Archivos que coinciden con un patrón

Un sinónimo de git add es git stage: es el mismo comando, y de ahí vienen el término «stage» y la expresión «stagear» un archivo.

git add -p: añadir solo una parte del archivo

Es el truco más infravalorado. Si en un mismo archivo hay dos cambios distintos mezclados, git add -p le mostrará cada fragmento y le preguntará si quiere añadirlo:

$ git add -p src/auth.js
@@ -12,7 +12,7 @@ function login(user) {
-  if (user.password = input) {
+  if (user.password === input) {
(1/2) Stage this hunk [y,n,q,a,d,s,e,?]?

y: añadir; n: omitir; s: dividir el fragmento en partes más pequeñas; q: salir. Así, de un solo archivo salen dos commits limpios.

Cómo comprobar qué entrará exactamente en el commit

git diff            # cambios que todavía NO están en el índice
git diff --staged   # lo que ya está en el índice y entrará en el commit

Una confusión frecuente: después de git add, un git diff normal no muestra nada. No significa que los cambios hayan desaparecido: están en el índice; use git diff --staged (sinónimo de --cached).

Cómo quitar un archivo del índice

git restore --staged file.js

Los cambios del archivo se conservan; simplemente deja de estar preparado para el commit. En versiones antiguas de Git se usaba git reset HEAD file.js, que sigue funcionando.

git commit: fijar los cambios

git commit -m "Corregir la comprobación de contraseña al iniciar sesión"
[main 3f2a9c1] Corregir la comprobación de contraseña al iniciar sesión
 1 file changed, 1 insertion(+), 1 deletion(-)

La respuesta incluye la rama, el hash corto del nuevo commit y estadísticas. En el commit entra solo el contenido del índice. Si después de git add volvió a modificar el archivo, esos cambios nuevos no entrarán en el commit hasta que los añada otra vez.

Opciones útiles de git commit

ComandoQué hace
git commitAbre el editor para escribir un mensaje de varias líneas
git commit -m "..."Mensaje directamente en el comando
git commit -am "..."Añade todos los archivos rastreados modificados y hace el commit; los archivos nuevos no entran
git commit -vMuestra el diff en el editor mientras escribe el mensaje
git commit --amendReescribe el último commit
git commit --allow-empty -m "..."Commit vacío, por ejemplo para relanzar el CI

Si el editor por defecto es Vim y se ha quedado atascado: escriba el mensaje, pulse Esc, teclee :wq y Enter. Para cambiar de editor: git config --global core.editor "code --wait" o nano.

Cómo escribir un buen mensaje de commit

El mensaje se lee medio año después, cuando alguien busca de dónde salió un bug. Debe responder a «qué y por qué», no a «qué hice hoy».

  • primera línea de 50–72 caracteres como máximo, con la esencia del cambio;
  • en imperativo o en tono neutro: «Añadir validación del email», «Fix login redirect»;
  • si hace falta, una línea en blanco y los detalles: por qué se hizo así, qué limitaciones hay;
  • un commit, un cambio lógico.

Mal: fix, cambios, wip, asdf. Bien: Corregir el fallo del carrito con la lista de productos vacía. Muchos equipos usan el formato Conventional Commits: feat: ..., fix: ..., docs: ....

git commit --amend: cómo corregir el último commit

¿Una errata en el mensaje o un archivo olvidado? No hace falta un nuevo commit «se me olvidó un archivo». Para eso existe amend.

Corregir el mensaje

git commit --amend -m "Corregir la comprobación de contraseña al iniciar sesión"

Añadir un archivo olvidado

git add forgotten.js
git commit --amend --no-edit

La opción --no-edit mantiene el mensaje anterior.

Lo importante sobre amend

--amend no «edita» el commit: crea uno nuevo con otro hash y sustituye al anterior. Mientras el commit solo esté en su equipo, es seguro. Si ya hizo git push, tras el amend un push normal será rechazado y tendrá que usar git push --force-with-lease. En ramas compartidas donde trabajan otras personas no conviene hacerlo: reescribiría un historial sobre el que ellas ya están construyendo su trabajo.

Si hizo el amend por error, el commit anterior se encuentra en git reflog y puede volver a él con git reset --soft HEAD@{1}.

Errores típicos

«nothing to commit, working tree clean»

No hay cambios: todo está ya confirmado, o está editando un archivo en otra carpeta. Revise git status y la ruta del proyecto.

«no changes added to commit»

Hay archivos modificados, pero no están en el índice. Ejecute git add o use git commit -am para los archivos ya rastreados.

«Please tell me who you are»

No ha configurado nombre ni e-mail. Ejecute una sola vez git config --global user.name "Nombre" y git config --global user.email "correo".

Ha incluido algo de más en el commit

Si el commit aún no se ha enviado, deshágalo conservando los cambios en el índice: git reset --soft HEAD~1. Después quite lo que sobra con git restore --staged y vuelva a hacer el commit. Si en el commit se coló un secreto, considérelo comprometido y genere uno nuevo.

git add . añadió basura

Configure .gitignore de antemano y revise git status antes del commit. Un archivo ya rastreado solo deja de rastrearse tras git rm --cached archivo.

Qué es realmente un commit

Un commit no guarda la diferencia con la versión anterior, sino una instantánea de todo el proyecto: una referencia al árbol de archivos, una referencia al commit padre, el autor, la fecha y el mensaje. Los archivos sin cambios no se copian: Git apunta a objetos ya guardados, por lo que el historial ocupa poco.

El hash del commit (por ejemplo, 3f2a9c1) se calcula a partir de todo ese contenido. Cambie una sola letra del mensaje y obtendrá otro hash. Por eso --amend y rebase crean commits nuevos en lugar de modificar los antiguos, y por eso un historial reescrito entra en conflicto con las copias de sus compañeros.

Para ver el historial de forma resumida:

git log --oneline --graph -10

Cada línea es un commit; si los mensajes de su historial se entienden sin abrir el diff, lo está haciendo bien.

El ciclo de trabajo diario

git status                 # qué ha cambiado
git diff                   # revisar los cambios
git add -p                 # seleccionar lo necesario
git diff --staged          # comprobar qué entrará en el commit
git commit -m "Descripción clara"
git log --oneline -5       # confirmar que el commit está ahí
git push                   # enviar al servidor

Un commit guarda los cambios solo en local. Para que lleguen a GitHub u otro servidor hace falta git push.

Conclusión

git add prepara la siguiente instantánea en el índice, git status y git diff --staged muestran qué entrará en ella, y git commit la registra en el historial. Haga commits pequeños y lógicos con mensajes claros, y para pequeñas correcciones del último commit use git commit --amend, siempre antes del push. El índice y el esquema de dos pasos add → commit se trabajan en la práctica en el curso de Git.

Preguntas frecuentes

¿Con qué frecuencia hay que hacer commits?

Cada vez que termine un cambio lógico y el proyecto funcione. Es mejor muchos commits pequeños que uno enorme al final del día.

¿Existe en Git un comando git save?

No, ese comando no existe. Guardar es git add más git commit, y para apartar temporalmente un trabajo a medias está git stash.

¿Cómo veo qué contenía un commit?

El comando git show hash muestra el autor, el mensaje y todos los cambios del commit. Sin hash, muestra el último commit.

¿En qué se diferencia git add . de git add -A?

En las versiones actuales de Git ambos añaden archivos nuevos, modificados y eliminados. La diferencia es el alcance: git add . trabaja con la carpeta actual y sus subcarpetas, y git add -A con todo el repositorio.

¿Se puede modificar un commit anterior, no el último?

Sí, con un rebase interactivo: git rebase -i hash-del-padre y después marcar el commit como edit o reword. Hágalo solo con commits que aún no se hayan enviado a una rama compartida.

Aprende este tema en vídeo

Este tema se explica a fondo y con práctica en el curso «Git desde cero hasta desarrollador seguro».

Ir al curso