restic forget con etiquetas: por qué --keep-last 1 borró también tus otras copias
con 3 snapshots diario y 3 mensual de la misma carpeta, forget --keep-last 1 conserva 1 y borra 5; con --group-by host,paths,tags conserva 1 de cada etiqueta (borra 4).
Contenido
Este artículo no contiene enlaces de afiliado.
Etiquetar copias (--tag diario, --tag mensual) parece una forma de tener políticas distintas. Pero restic forget agrupa por host y ruta, no por etiqueta, y eso puede borrar más de lo esperado. Se probó con un repositorio desechable.
Condiciones: restic 0.16.4 en Linux arm64, repositorio local, una carpeta con un fichero, seis snapshots (3 con --tag diario, 3 con --tag mensual), todos de la misma carpeta y máquina. Script completo al final. No se probó con varias máquinas ni con políticas --keep-daily o --keep-monthly.
Resultado
| Comando | Snapshots conservados | Borrados |
|---|---|---|
forget --keep-last 1 (simulado con --dry-run) |
1 | 5 |
forget --keep-last 1 --group-by host,paths,tags (real) |
2 (1 por etiqueta) | 4 |
Por defecto el grupo es host,paths: como las dos etiquetas apuntaban a la misma carpeta, restic las trató como un solo grupo y dejó solo el último snapshot, de una sola etiqueta.
Qué hacer
- Revisa siempre con
--dry-runantes de cambiar una política. Ver forget y prune. - Si usas etiquetas para políticas distintas, añade
--group-by host,paths,tags, o filtra con--tagy ejecuta un forget por etiqueta. - Cuidado con el segundo caso: la prueba no verificó
--tagcombinado con otras políticas.
Script completo
#!/bin/bash
# restic forget grouping: same folder, two tags. Usage: test-restic-tags.sh WORKDIR
W=$1; rm -rf "$W"; mkdir -p "$W/datos"
export RESTIC_PASSWORD=prueba-desechable
R="$W/repo"; restic init -r "$R" >/dev/null
for i in 1 2 3; do
echo "diario $i" > "$W/datos/a.txt"; restic -r "$R" backup "$W/datos" --tag diario --quiet
echo "mensual $i" > "$W/datos/a.txt"; restic -r "$R" backup "$W/datos" --tag mensual --quiet
done
n() { restic -r "$R" snapshots --json | python3 -c 'import sys,json,collections;c=collections.Counter(",".join(s.get("tags",[])) for s in json.load(sys.stdin));print(dict(c))'; }
echo "== inicio"; n
echo "== 1) forget --keep-last 1 (agrupa por host,paths)"; restic -r "$R" forget --keep-last 1 --dry-run | grep -E "^(keep|remove) "
echo "== 2) forget --keep-last 1 --group-by host,paths,tags (real)"; restic -r "$R" forget --keep-last 1 --group-by host,paths,tags | grep -E "^(keep|remove) "
echo "== final"; n