CommunityRecherche & Datenanalysegithub.com

dragon-fish/config-file-versioning

Automatische Versionierung lokaler Config-Dateien über Git + OS-Dateiüberwachung. Eine Einsetzbare-Fertigkeit für KI-Coding-Agenten (Claude Code, Codex, Gemini CLI etc.).

Was ist config-file-versioning?

Diese Fertigkeit implementiert eine automatische Git-basierte Versionierung für kleine, wichtige lokale Konfigurationsdateien, die nicht unbemerkt überschrieben werden sollen. Sie überwacht Dateien auf Änderungen (über launchd, systemd oder andere Dateiüberwachungstools) und erstellt innerhalb von 10 Sekunden automatisch einen Git-Commit in einem separaten Repository. Ein Rollback auf jede historische Version ist jederzeit möglich. Die Fertigkeit arbeitet plattformunabhängig (macOS, Linux), ist ereignisgesteuert (kein ständiger Polling-Prozess) und speichert das Git-Repository außerhalb des Arbeitsverzeichnisses, sodass die Historie erhalten bleibt, selbst wenn die überwachten Dateien gelöscht werden. Sie ist ideal für Entwickler, die verhindern möchten, dass Tools oder eigene Fehler wichtige Konfigurationen (z.B. ~/.ssh/config, VS Code-Einstellungen) überschreiben.

Funktioniert mit✓Claude Code✓Codex CLI~Cursor✓Gemini CLI
npx skills add dragon-fish/config-file-versioning

Installed? Explore more Recherche & Datenanalyse skills: affaan-m/uspto-database, affaan-m/scholar-evaluation, affaan-m/literature-review · View all 6 →

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Fertigkeit: Config File Versioning

Erstellt automatische Versions-Backups für "kleine + wichtige + nicht unbemerkt überschreibbare" lokale Konfigurationsdateien.

Bei jeder tatsächlichen Inhaltsänderung einer überwachten Datei wird innerhalb von 10 Sekunden automatisch ein Git-Commit erstellt, der in einem lokalen, separaten Git-Repository gespeichert wird. Ein-Klick-Rollback auf jede historische Version.


Wann verwenden

Verwende diese Fertigkeit, wenn der Benutzer eines der folgenden Auslösesignale von sich gibt:

  • "Füge für automatische Versionierung/Backup/Überschreibschutz hinzu"
  • "Ich möchte nicht, dass ein Programm wieder meine überschreibt"
  • "Automatischer Commit, wenn sich ändert"
  • "Referenziere und erstelle Backup für "
  • Der Benutzer erwähnt, dass eine wichtige Konfiguration durch ein Tool oder versehentlich überschrieben/verloren wurde und fragt, wie man das in Zukunft verhindern kann.

Nicht geeignet für:

  • Große Code-Repositories (hier reicht der normale Git-Workflow)
  • Maschinenübergreifende Synchronisation (diese Fertigkeit erstellt nur lokale Versionshistorie; für Synchronisation zusätzlich Syncthing oder manuellen Git-Push zu einem privaten Remote verwenden)
  • Häufig sich ändernde Dateien (.bash_history, history.jsonl usw. – das würde zu vielen Commits führen)

Architekturübersicht

   <Geschützte Datei>           (tatsächlicher Pfad, z.B. ~/.ssh/config)
        │ Änderung
        ▼
   OS-Dateiüberwachung
   ┌──────────────────────────────────┬──────────────────────┬─────────┐
   │ macOS: launchd WatchPaths        │ Linux: systemd .path │ Sonstige│
   └──────────────────────────────────┴──────────────────────┴─────────┘
        │ Auslösung (nach 10s Drosselung)
        ▼
   auto-commit.sh
        │ git add -A → nur wenn staged Diff nicht leer ist, commit
        ▼
   <BACKUP_ROOT>/<domain>-config.git/   ← eigentliches Git-Repo (separate-git-dir)
        ▲
        │ Verbindung durch ".git" im Worktree (eine Zeile `gitdir: ...`)

Wichtige Designentscheidungen:

DesignBegründung
Jeder Config-Bereich eigenes Repository (nicht in einem großen Repository zusammengefasst)Saubere Historie; unabhängiges Aktivieren/Deaktivieren/Migrieren möglich
Separate-git-dirWenn das Worktree-Verzeichnis durch ein Programm gelöscht wird, bleibt die Historie im <BACKUP_ROOT> erhalten
Whitelist .gitignore (* + !<geschützte Datei>)Verhindert das versehentliche Aufnehmen von Laufzeitdaten, Caches oder temporären Dateien im selben Verzeichnis
Ereignisgesteuerte Überwachung + Drosselung (Standard 10s)Kein ständig laufender Prozess im Leerlauf; vermeidet mehrere Commits bei einem Schreibvorgang
Prüfung im Commit-Skript: git diff --cached --quietWenn sich der Inhalt nicht geändert hat (nur mtime), wird still beendet

Implementierungsschritte

Schritt 0: 4 Variablen mit dem Benutzer abstimmen

VariableBedeutungEmpfohlener Standardwert
<DOMAIN>Kurzname des Konfigurationsbereichs (nur Kleinbuchstaben, Ziffern, Bindestriche – als Verzeichnisname/Label-Suffix)Mit Benutzer besprechen; z.B. ssh / zsh / vscode / claude
<WORKTREE>Absoluter Pfad des Verzeichnisses mit der zu schützenden Datei (Git-Worktree-Root)Normalerweise das Verzeichnis, in dem sich die zu überwachende Datei befindet
<FILES>Liste der absoluten Pfade der zu überwachenden Dateien (≥ 1)Vom Benutzer festgelegt
<BACKUP_ROOT>Stammverzeichnis für Repository + Skripte + Service-VorlagenMuss erfragt werden: Standardempfehlung ~/.local/share/config-versioning/<DOMAIN>/ (XDG-Datenverzeichnis-Konvention); falls der Benutzer bereits ein dediziertes Backup-/Sync-Verzeichnis hat (z.B. ~/Documents/backups/, ~/Sync/..., eigene Sandbox), entscheidet der Benutzer

Schritt 1: Datenverzeichnis erstellen + Git-Repo initialisieren

mkdir -p "<BACKUP_ROOT>"

mkdir -p "<WORKTREE>"
cd "<WORKTREE>" && git init -q -b main

Schritt 2: Whitelist .gitignore schreiben

Kopiere templates/gitignore-whitelist nach <WORKTREE>/.gitignore und füge für jeden Pfad in <FILES> relativ zu <WORKTREE> eine Zeile !<relativer-Pfad> hinzu.

Beispiel: worktree=~/.ssh, zu schützen: ~/.ssh/config und ~/.ssh/known_hosts, füge hinzu:

!config
!known_hosts

Schritt 3: Ersten Commit erstellen

cd "<WORKTREE>"
git add -A
git commit -q -m "chore: initial snapshot of <DOMAIN> config"

Nicht -c user.name/-c user.email verwenden, um die globale Git-Konfiguration zu überschreiben – lass Git die Benutzereinstellungen verwenden. Das Repository ist rein lokal, wird nicht gepusht, der Autor ist unwichtig.

Schritt 4: .git-Verzeichnis nach <BACKUP_ROOT> verschieben und Gitdir-Zeiger setzen

GITDIR="<BACKUP_ROOT>/<DOMAIN>-config.git"
mv "<WORKTREE>/.git" "$GITDIR"
echo "gitdir: $GITDIR" > "<WORKTREE>/.git"
git -C "$GITDIR" config core.worktree "<WORKTREE>"

Schritt 5: Auto-Commit-Skript kopieren und anpassen

Kopiere templates/auto-commit.sh nach <BACKUP_ROOT>/auto-commit.sh und ersetze die 2 Platzhalter:

PlatzhalterErsetzen durch
__WORKTREE__Absoluter Pfad von <WORKTREE>
__LOG__Pfad für Logdatei, empfohlen ~/Library/Logs/config-file-versioning.log (macOS) oder ~/.local/state/config-file-versioning.log (Linux)

chmod +x darauf ausführen.

Schritt 6: Überwachungsebene installieren (nach Betriebssystem verzweigen)

6a. macOS (launchd LaunchAgent)

Kopiere templates/launchagent.plist und ersetze die Platzhalter:

PlatzhalterErsetzen durch
__LABEL__local.<BENUTZER>.<DOMAIN>-config-watch (Präfix local. vermeidet Konflikte; <BENUTZER> mit $USER ersetzen)
__SCRIPT_PATH__Absoluter Pfad von <BACKUP_ROOT>/auto-commit.sh
__WATCH_PATHS__Jede Datei in <FILES> in ein Paar <string>...</string> einschließen, alles in <array>
__LOG__Wie in Schritt 5

Zwei Kopien erstellen (zur Sicherstellung der Portabilität):

  1. <BACKUP_ROOT>/<LABEL>.plist (Backup-Vorlage)
  2. ~/Library/LaunchAgents/<LABEL>.plist (tatsächlich aktiv)

Laden:

launchctl unload "$HOME/Library/LaunchAgents/<LABEL>.plist" 2>/dev/null
launchctl load   "$HOME/Library/LaunchAgents/<LABEL>.plist"
launchctl list | grep "<LABEL>"   # Überprüfen, ob registriert

6b. Linux (systemd path unit)

Kopiere templates/systemd.path und templates/systemd.service nach ~/.config/systemd/user/ und benenne sie in <DOMAIN>-config-watch.path und <DOMAIN>-config-watch.service um. Ersetze die Platzhalter in den Dateien. Dann:

systemctl --user daemon-reload
systemctl --user enable --now <DOMAIN>-config-watch.path

6c. Sonstige / Fallback

Jedes Tool, das "watch + Befehl ausführen" kann, ist geeignet:

  • gitwatch (plattformübergreifend, Shell): brew install gitwatch oder apt install gitwatch
  • fswatch + eigener Daemon: fswatch <FILES> | xargs -n1 <BACKUP_ROOT>/auto-commit.sh
  • inotifywait (Linux) + Shell-Schleife

Den Watcher-Prozess dem entsprechenden Service-Manager der Plattform anvertrauen (OpenRC, runit, launchd, systemd).

Schritt 7: End-to-End-Test (zwingend, nicht überspringbar)

Eine überwachte Datei ändern, etwas länger als das Drosselungsintervall warten (z.B. 12 Sekunden bei 10s Drosselung), dann Log und Git-Log überprüfen, ob jeweils ein Eintrag hinzugekommen ist. Zuerst ein temporäres Feld einfügen, dann wieder entfernen – erwartet werden 2 Commits:

# Beispiel: JSON-Datei mit temporärem Schlüssel _autoCommitTest
# sleep 12 (bei Drosselung=10s)
tail -2 "<LOG>"
git -C "<WORKTREE>" log --oneline | head -3

Schritt 8: README schreiben

Jedes <BACKUP_ROOT> sollte eine eigene README.md enthalten, um zukünftige Migrationen zu erleichtern. Mindestens enthalten:

  • Zweck (warum dieses Setup existiert)
  • Tabelle der Dateien
  • Tägliche Befehle (Historie anzeigen, Rollback, Watcher-Status prüfen, Log anzeigen)
  • Wartung (neue Überwachungsdatei hinzufügen, Drosselungsintervall ändern)
  • Schritte zum Wiederaufbau auf einem neuen Rechner
  • Vollständige Deinstallationsschritte

Anti-Patterns (explizit vermeiden)

❌ Falscher Ansatz✅ Richtig
Mehrere Config-Bereiche in dasselbe Git-Repository packenEin Bereich ein Repository
.git im Worktree belassenNach <BACKUP_ROOT> verschieben und Gitdir-Zeiger verwenden
Blacklist .gitignore verwendenWhitelist verwenden
End-to-End-Test überspringenZwingend durchführen, sicherstellen, dass Commits tatsächlich erstellt werden
Plist/Service-Unit nur im Systemverzeichnis ablegen, nicht als Vorlage im <BACKUP_ROOT>An beiden Orten ablegen, damit das Verzeichnis autark und migrierbar ist
Beim Commit auf ein öffentliches Remote pushenVerboten – Konfigurationen können Tokens / sensible Daten enthalten, rein lokales Repository
git user.name/email im auto-commit.sh fest codierenDer globalen Git-Konfiguration überlassen; Skripte sollten keine persönlichen Daten enthalten
Fswatch mit KeepAlive=true dauerhaft laufen lassenBevorzugt ereignisgesteuert (WatchPaths / .path unit), kein dauerhafter Prozess

Behandlung von Grenzfällen

  • Worktree-Verzeichnis existiert nicht: Zuerst mkdir -p ausführen. Wenn es das erste Mal ist, existiert die zu überwachende Datei möglicherweise auch nicht – klären, ob zuerst eine leere Datei erstellt werden soll.
  • Überwachte Datei ist ein symbolischer Link: Im Watcher sowohl den Link-Pfad als auch das reale Ziel überwachen, da manche Schreibvorgänge nur einen der beiden auslösen.
  • Überwachte Datei ist binär: Funktioniert trotzdem (Git speichert Blob), aber der Diff zeigt keinen Inhalt.
  • Gleiches Label/Service existiert bereits: Zuerst das alte unloaden/deaktivieren, dann das neue laden.
  • Mehrere Schreibvorgänge innerhalb des Drosselungsfensters: Mehrere Änderungen innerhalb des Drosselungsfensters werden zu einem einzigen Commit zusammengefasst (erwünschtes Verhalten).
  • Atomare Schreibvorgänge (write-temp + rename): launchd WatchPaths löst normalerweise korrekt aus; falls ein bestimmtes Programm zu einem verpassten Commit führt, dem Benutzer empfehlen, auf KeepAlive + gitwatch / fswatch-Hauptschleife umzusteigen.

Vorlagendateien


Designphilosophie

  1. Sichtbar + lesbar + manuell bearbeitbar: Die Versionshistorie ist reines Text-Git; jeder, der Git versteht, kann Änderungen lokalisieren/zurücksetzen, ohne auf eine GUI angewiesen zu sein.
  2. Ereignisgesteuert ≫ Polling: Reduziert CPU-/Festplattenverbrauch im Leerlauf.
  3. Ausfallsicher: Das Commit-Skript hat keine Nebenwirkungen – schlägt cd fehl oder ist der Diff leer, wird still beendet, ohne das Worktree zu beschädigen.
  4. Verzeichnis autark: <BACKUP_ROOT> enthält Daten + Skripte + plist/unit-Vorlagen + README – das gesamte Verzeichnis kann kopiert werden, um die Funktionalität auf einem neuen Rechner wiederherzustellen.
  5. Kein Push: Vermeidet das Hochladen privater Konfigurationen auf ein entferntes Repository; für externe Backups dateibasierte Lösungen verwenden (Time Machine / Backblaze / verschlüsseltes Syncthing).

Verwandte Skills