Implement sync script and setup documentation
This commit is contained in:
5 files changed
+1400
No files matched your search
@@ -0,0 +1,61 @@
|
||||
[0;34m[2026-09-28 18:17:00][0m ═══════════════════════════════════════════════════════════
|
||||
[0;34m[2026-09-28 18:17:00][0m Modus: status
|
||||
[0;34m[2026-09-28 18:17:00][0m ═══════════════════════════════════════════════════════════
|
||||
[0;34m[2026-09-28 18:17:00][0m Status: Vergleiche Repo mit Home-Dir...
|
||||
[0;34m[2026-09-28 18:17:03][0m ═══════════════════════════════════════════════════════════
|
||||
[0;34m[2026-09-28 18:17:03][0m Modus: status
|
||||
[0;34m[2026-09-28 18:17:03][0m ═══════════════════════════════════════════════════════════
|
||||
[0;34m[2026-09-28 18:17:03][0m Status: Vergleiche Repo mit Home-Dir...
|
||||
[0;34m[2026-09-28 18:17:50][0m ═══════════════════════════════════════════════════════════
|
||||
[0;34m[2026-09-28 18:17:50][0m Modus: status
|
||||
[0;34m[2026-09-28 18:17:50][0m ═══════════════════════════════════════════════════════════
|
||||
[0;34m[2026-09-28 18:17:50][0m Status: Vergleiche Repo mit Home-Dir...
|
||||
[0;34m[2026-09-28 18:17:53][0m ═══════════════════════════════════════════════════════════
|
||||
[0;34m[2026-09-28 18:17:53][0m Modus: status
|
||||
[0;34m[2026-09-28 18:17:53][0m ═══════════════════════════════════════════════════════════
|
||||
[0;34m[2026-09-28 18:17:53][0m Status: Vergleiche Repo mit Home-Dir...
|
||||
[0;34m[DEBUG][0m ✓ identisch: .bash_aliases
|
||||
[0;34m[DEBUG][0m ✓ identisch: .gitconfig
|
||||
[0;34m[DEBUG][0m ✓ identisch: .gitconfig-architeq
|
||||
[0;34m[DEBUG][0m ✓ identisch: .gitconfig-bc
|
||||
[0;34m[DEBUG][0m ✓ identisch: .gitconfig-nettworks
|
||||
[0;34m[DEBUG][0m ✓ identisch: .gitconfig-private
|
||||
[0;34m[DEBUG][0m ✓ identisch: .gitconfig-ti8m
|
||||
[0;34m[DEBUG][0m ✓ identisch: .gitignore_global
|
||||
[0;34m[DEBUG][0m ✓ identisch: .npmrc
|
||||
[0;34m[DEBUG][0m ✓ identisch: .p10k.zsh
|
||||
[0;34m[DEBUG][0m ✓ identisch: .profile
|
||||
[0;34m[DEBUG][0m ✓ identisch: .testcontainers.properties
|
||||
[0;34m[DEBUG][0m ✓ identisch: .zshrc
|
||||
[0;34m[DEBUG][0m ✓ identisch: getsizes.sh
|
||||
[0;32m[OK][0m Status-Zusammenfassung:
|
||||
[0;34m[2026-09-28 18:17:53][0m ═══════════════════════════════════════════════════════════
|
||||
[0;32m[OK][0m Abgeschlossen
|
||||
[0;34m[2026-09-28 18:18:40][0m ═══════════════════════════════════════════════════════════
|
||||
[0;34m[2026-09-28 18:18:40][0m Modus: list
|
||||
[0;34m[2026-09-28 18:18:40][0m ═══════════════════════════════════════════════════════════
|
||||
[0;34m[2026-09-28 18:18:40][0m Liste alle verwalteten Dateien:
|
||||
[0;34m[2026-09-28 18:18:40][0m ═══════════════════════════════════════════════════════════
|
||||
[0;32m[OK][0m Abgeschlossen
|
||||
[0;34m[2026-09-28 18:18:43][0m ═══════════════════════════════════════════════════════════
|
||||
[0;34m[2026-09-28 18:18:43][0m Modus: push
|
||||
[0;34m[2026-09-28 18:18:43][0m DRY-RUN: Keine Änderungen werden vorgenommen
|
||||
[0;34m[2026-09-28 18:18:43][0m ═══════════════════════════════════════════════════════════
|
||||
[0;34m[2026-09-28 18:18:43][0m Push: Synchronisiere Repo-Dateien ins Home-Dir...
|
||||
[0;34m[DEBUG][0m ⊙ unverändert: .bash_aliases
|
||||
[0;34m[DEBUG][0m ⊙ unverändert: .gitconfig
|
||||
[0;34m[DEBUG][0m ⊙ unverändert: .gitconfig-architeq
|
||||
[0;34m[DEBUG][0m ⊙ unverändert: .gitconfig-bc
|
||||
[0;34m[DEBUG][0m ⊙ unverändert: .gitconfig-nettworks
|
||||
[0;34m[DEBUG][0m ⊙ unverändert: .gitconfig-private
|
||||
[0;34m[DEBUG][0m ⊙ unverändert: .gitconfig-ti8m
|
||||
[0;34m[DEBUG][0m ⊙ unverändert: .gitignore_global
|
||||
[0;34m[DEBUG][0m ⊙ unverändert: .npmrc
|
||||
[0;34m[DEBUG][0m ⊙ unverändert: .p10k.zsh
|
||||
[0;34m[DEBUG][0m ⊙ unverändert: .profile
|
||||
[0;34m[DEBUG][0m ⊙ unverändert: .testcontainers.properties
|
||||
[0;34m[DEBUG][0m ⊙ unverändert: .zshrc
|
||||
[0;34m[DEBUG][0m ⊙ unverändert: getsizes.sh
|
||||
[0;32m[OK][0m Push abgeschlossen: 0 kopiert, 0 Backups, 0 ausgelassen
|
||||
[0;34m[2026-09-28 18:18:43][0m ═══════════════════════════════════════════════════════════
|
||||
[0;32m[OK][0m DRY-RUN abgeschlossen (keine Änderungen)
|
||||
Executable
+150
@@ -0,0 +1,150 @@
|
||||
#!/bin/bash
|
||||
# Quick-Start Guide für sync-home-content.sh
|
||||
|
||||
cat << 'EOF'
|
||||
|
||||
╔════════════════════════════════════════════════════════════════════════════╗
|
||||
║ Quick-Start: home-content Synchronisierung ║
|
||||
╚════════════════════════════════════════════════════════════════════════════╝
|
||||
|
||||
📋 KURZVERSION (3 Schritte):
|
||||
|
||||
1. Status prüfen:
|
||||
./sync-home-content.sh status
|
||||
|
||||
2. Trockentest:
|
||||
./sync-home-content.sh sync --dry-run
|
||||
|
||||
3. Synchronisieren:
|
||||
./sync-home-content.sh sync
|
||||
|
||||
|
||||
═══════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
🎯 Welcher Modus passt?
|
||||
|
||||
┌─ Lokal neue .gitconfig erstellt / bearbeitet
|
||||
│ → ./sync-home-content.sh pull
|
||||
│
|
||||
├─ Git-Pull durchgeführt, Repo hat Updates
|
||||
│ → ./sync-home-content.sh push
|
||||
│
|
||||
├─ "Weiß nicht, was geändert wurde" (safer)
|
||||
│ → ./sync-home-content.sh sync
|
||||
│
|
||||
├─ Nur schauen, nicht ändern
|
||||
│ → ./sync-home-content.sh status
|
||||
│
|
||||
└─ Alte Backups löschen (>30 Tage)
|
||||
→ ./sync-home-content.sh cleanup
|
||||
|
||||
|
||||
═══════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
🛡️ IMMER SO:
|
||||
|
||||
TROCKENTEST vor echter Änderung:
|
||||
./sync-home-content.sh [modus] --dry-run
|
||||
|
||||
Dann mit -v (verbose) um Details zu sehen:
|
||||
./sync-home-content.sh [modus] --dry-run -v
|
||||
|
||||
|
||||
═══════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
💾 BACKUPS:
|
||||
|
||||
Alle Backups sind in: .sync-backups/
|
||||
|
||||
Restore eines Backups:
|
||||
cp .sync-backups/.gitconfig.20260928_150000.backup home-content/.gitconfig
|
||||
|
||||
Alte Backups löschen:
|
||||
./sync-home-content.sh cleanup
|
||||
|
||||
|
||||
═══════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
📝 CHECKLISTE für Anfänger:
|
||||
|
||||
☐ Stehe im Verzeichnis: ~/mac-home
|
||||
☐ Führe Status aus: ./sync-home-content.sh status
|
||||
☐ Lese die Zusammenfassung sorgfältig
|
||||
☐ Führe mit --dry-run aus: ./sync-home-content.sh [modus] --dry-run
|
||||
☐ Stimmst du mit den Änderungen überein? (JA → nächster Schritt)
|
||||
☐ Führe ohne --dry-run aus: ./sync-home-content.sh [modus]
|
||||
☐ Prüfe Logs: tail .sync-home-content.log
|
||||
☐ Backups prüfen: ls -la .sync-backups/
|
||||
|
||||
|
||||
═══════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
⚡ HÄUFIGE SZENARIEN:
|
||||
|
||||
1️⃣ Neue dotfiles lokal bearbeitet → Repo speichern
|
||||
|
||||
./sync-home-content.sh status # Was wurde geändert?
|
||||
./sync-home-content.sh pull --dry-run # Trockentest
|
||||
./sync-home-content.sh pull # Echte Sync
|
||||
cd home-content && git commit -am "Update" && git push
|
||||
|
||||
2️⃣ Git-Update von Team → Lokal anwenden
|
||||
|
||||
git pull # Repository updaten
|
||||
./sync-home-content.sh push --dry-run # Trockentest
|
||||
./sync-home-content.sh push # Echte Sync
|
||||
source ~/.zshrc # (bei .zshrc) neuladen
|
||||
|
||||
3️⃣ "Ich weiß nicht was los ist" (safest)
|
||||
|
||||
./sync-home-content.sh sync --dry-run -v # Ausführlich sehen
|
||||
./sync-home-content.sh sync # Bidirektional lösen
|
||||
|
||||
4️⃣ Ich habe versehentlich was kaputt gemacht
|
||||
|
||||
ls -lh .sync-backups/ # Backup finden
|
||||
cp .sync-backups/DATEI.*.backup home-content/DATEI
|
||||
./sync-home-content.sh push # Restore
|
||||
|
||||
|
||||
═══════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
❓ FRAGEN:
|
||||
|
||||
Q: Verliere ich lokale Änderungen?
|
||||
A: NEIN! Es wird immer ein Backup erstellt bevor überschrieben wird.
|
||||
.sync-backups/ enthält die alten Versionen.
|
||||
|
||||
Q: Was ist der Unterschied pull vs push?
|
||||
A: PULL = Home → Repo (lokale Änderungen ins Repository)
|
||||
PUSH = Repo → Home (Repository ins lokale Home-Dir)
|
||||
|
||||
Q: Kann ich mehrere Dateien gleichzeitig mit --dry-run testen?
|
||||
A: JA! --dry-run tut nix, du kannst mehrmals hintereinander testen.
|
||||
|
||||
Q: Wie oft sollte ich cleanup laufen lassen?
|
||||
A: Monatlich ist sinnvoll. Script löscht nur Backups >30 Tage.
|
||||
|
||||
Q: Kann ich es automatisieren (Cron)?
|
||||
A: JA! Aber nutze `sync` mode im non-interactive (Standard).
|
||||
Im .sync-backups musst du selbst aufräumen.
|
||||
|
||||
|
||||
═══════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
🔗 WEITERE INFOS:
|
||||
|
||||
Detaillierte Doku: SYNC-STRATEGY.md
|
||||
Logs: .sync-home-content.log
|
||||
Hilfe: ./sync-home-content.sh -h
|
||||
|
||||
|
||||
═══════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
🚀 READY? Let's go:
|
||||
|
||||
cd ~/mac-home
|
||||
./sync-home-content.sh status
|
||||
|
||||
EOF
|
||||
|
||||
+227
@@ -0,0 +1,227 @@
|
||||
# mac-home Synchronisierungs-Toolset
|
||||
|
||||
Drei hilfreiche Werkzeuge um deine Dotfiles (`~/.zshrc`, `~/.gitconfig`, etc.) zwischen deinem Home-Directory und diesem Repository zu synchronisieren.
|
||||
|
||||
## 📦 Dateien
|
||||
|
||||
| Datei | Größe | Zweck |
|
||||
|-------|-------|-------|
|
||||
| **`sync-home-content.sh`** | 17 KB | Hauptscript mit 6 Synchronisierungs-Modi |
|
||||
| **`SYNC-STRATEGY.md`** | 10 KB | Ausführliche Dokumentation & Best Practices |
|
||||
| **`QUICK-START.sh`** | 6 KB | Quick-Start Guide (diesen hier lesen!) |
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Schnellstart
|
||||
|
||||
```bash
|
||||
cd ~/mac-home
|
||||
|
||||
# 1. Status anschauen
|
||||
./sync-home-content.sh status
|
||||
|
||||
# 2. Mit --dry-run testen (KEINE Änderungen)
|
||||
./sync-home-content.sh sync --dry-run
|
||||
|
||||
# 3. Echte Synchronisierung
|
||||
./sync-home-content.sh sync
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Die 6 Modi
|
||||
|
||||
### 1. **STATUS** — Nur Information
|
||||
Zeigt welche Dateien geändert wurden (ohne zu ändern).
|
||||
```bash
|
||||
./sync-home-content.sh status
|
||||
```
|
||||
|
||||
### 2. **PUSH** — Repo → Home
|
||||
Kopiert vom Repository ins lokale Home-Directory.
|
||||
**Nutze wenn:** Git-Update vorhanden.
|
||||
```bash
|
||||
./sync-home-content.sh push
|
||||
```
|
||||
|
||||
### 3. **PULL** — Home → Repo
|
||||
Kopiert vom Home-Directory ins Repository.
|
||||
**Nutze wenn:** Lokal Dateien bearbeitet.
|
||||
```bash
|
||||
./sync-home-content.sh pull
|
||||
```
|
||||
|
||||
### 4. **SYNC** — Bidirektional
|
||||
Intelligente 2-Wege Synchronisierung.
|
||||
**Nutze wenn:** Du unsicher bist, was verändert wurde.
|
||||
```bash
|
||||
./sync-home-content.sh sync
|
||||
```
|
||||
|
||||
### 5. **CLEANUP** — Alte Backups löschen
|
||||
Entfernt Backups älter als 30 Tage.
|
||||
```bash
|
||||
./sync-home-content.sh cleanup
|
||||
```
|
||||
|
||||
### 6. **LIST** — Verwaltete Dateien
|
||||
Zeigt alle Dateien, die versioniert sind.
|
||||
```bash
|
||||
./sync-home-content.sh list
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🛡️ Sicherheitsfeatures
|
||||
|
||||
✅ **Backups:** Vor jeder Änderung wird ein Backup erstellt (`.sync-backups/`)
|
||||
✅ **Dry-Run:** Mit `--dry-run` testen ohne zu ändern
|
||||
✅ **Checksummen:** Content-basierter Vergleich (md5sum, nicht Timestamp)
|
||||
✅ **Logs:** Alles protokolliert in `.sync-home-content.log`
|
||||
✅ **Smart Conflict-Handling:** Neuere Version gewinnt automatisch (oder interaktiv)
|
||||
|
||||
---
|
||||
|
||||
## 💡 Typische Workflows
|
||||
|
||||
### Scenario 1: Lokal `.zshrc` bearbeitet
|
||||
```bash
|
||||
./sync-home-content.sh status # "≠ geändert im Home: .zshrc"
|
||||
./sync-home-content.sh pull --dry-run # Test
|
||||
./sync-home-content.sh pull # Sync ins Repo
|
||||
git -C home-content commit -am "Update .zshrc"
|
||||
git -C home-content push
|
||||
```
|
||||
|
||||
### Scenario 2: Git-Pull → Home updaten
|
||||
```bash
|
||||
git pull # Repository updaten
|
||||
./sync-home-content.sh push --dry-run # Test
|
||||
./sync-home-content.sh push # Sync ins Home
|
||||
source ~/.zshrc # (bei .zshrc reload)
|
||||
```
|
||||
|
||||
### Scenario 3: "Weiß nicht was los ist"
|
||||
```bash
|
||||
./sync-home-content.sh sync --dry-run -v # Ausführlich sehen
|
||||
./sync-home-content.sh sync # Bi-direktional sync
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📋 Optionen
|
||||
|
||||
| Flag | Effekt | Beispiel |
|
||||
|------|--------|---------|
|
||||
| `-d, --dry-run` | Zeige nur, ohne zu ändern | `./sync status --dry-run` |
|
||||
| `-v, --verbose` | Detaillierter Output | `./sync status -v` |
|
||||
| `-i, --interactive` | Frage bei Konflikten | `./sync sync --interactive` |
|
||||
| `--no-backup` | Keine Backups erstellen | `./sync push --no-backup` |
|
||||
| `-h, --help` | Zeige Hilfe | `./sync -h` |
|
||||
|
||||
---
|
||||
|
||||
## 📚 Dokumentation
|
||||
|
||||
- **Quick-Start:** `./QUICK-START.sh` (ausgeben)
|
||||
- **Detaillierte Docs:** Lies `SYNC-STRATEGY.md`
|
||||
- **Logs:** `cat .sync-home-content.log`
|
||||
|
||||
---
|
||||
|
||||
## 🆘 Fehlerbehandlung
|
||||
|
||||
### Backup versehentlich gelöscht?
|
||||
```bash
|
||||
# Schaue in .sync-backups nach
|
||||
ls -lh .sync-backups/
|
||||
|
||||
# Restore
|
||||
cp .sync-backups/.gitconfig.20260928_150000.backup home-content/.gitconfig
|
||||
```
|
||||
|
||||
### Falsche Synchronisierung?
|
||||
```bash
|
||||
# Checksum-Mismatch? Das sind die gültigen Einträge:
|
||||
cd home-content && git ls-files
|
||||
```
|
||||
|
||||
### Script zu langsam?
|
||||
- Normal für ~14 Dateien < 1 Sek (md5sum overhead minimal)
|
||||
- Bei vielen Dateien: `seq-Verarbeitung` ist bewusst, nicht parallelisierbar
|
||||
|
||||
---
|
||||
|
||||
## ⚙️ Erweiterte Nutzung
|
||||
|
||||
### Alias für schnellen Zugriff
|
||||
```bash
|
||||
# In ~/.zshrc hinzufügen:
|
||||
alias synchome="~/mac-home/sync-home-content.sh"
|
||||
alias synchome-status="~/mac-home/sync-home-content.sh status"
|
||||
alias synchome-pull="~/mac-home/sync-home-content.sh pull --dry-run && ~/mac-home/sync-home-content.sh pull"
|
||||
```
|
||||
|
||||
### Cron-Job für regelmäßigen Sync
|
||||
```bash
|
||||
# Alle 2 Stunden
|
||||
0 */2 * * * cd ~/mac-home && ./sync-home-content.sh sync >> /tmp/sync-home.log 2>&1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔍 Strategie: Inhalt vs. Timestamp?
|
||||
|
||||
Das Script nutzt **md5sum für Erkennung** + **Timestamp für Konflikt-Auflösung**:
|
||||
|
||||
| Aspekt | Methode | Grund |
|
||||
|--------|---------|-------|
|
||||
| Änderung erkennen | md5sum (Content) | Zuverlässig, Zeitzone-unabhängig |
|
||||
| Konflikt lösen | Timestamp (mtime) | Welche Version ist neuerer? |
|
||||
| Nur in Repo? | git ls-files | Tracking nur versionierter Dateien |
|
||||
|
||||
---
|
||||
|
||||
## ✅ Best Practices
|
||||
|
||||
**IMMER TUN:**
|
||||
- ✓ Vor kritischen Änderungen `status` checken
|
||||
- ✓ Mit `--dry-run` testen bevor echte Sync
|
||||
- ✓ Logs regelmäßig prüfen: `tail .sync-home-content.log`
|
||||
- ✓ Alte Backups mit `cleanup` entfernen (monatlich)
|
||||
|
||||
**NICHT TUN:**
|
||||
- ✗ `--no-backup` ohne wichtigen Grund nutzen
|
||||
- ✗ `push` als Standard-Modus (zu aggressiv)
|
||||
- ✗ Mehrere Sync-Prozesse parallel laufen lassen
|
||||
- ✗ `.sync-backups/` von Hand löschen
|
||||
|
||||
---
|
||||
|
||||
## 📖 Weitere Ressourcen
|
||||
|
||||
- Detaillierte Erklärung der Modi: `SYNC-STRATEGY.md` (5 min Lesedauer)
|
||||
- Troubleshooting: `SYNC-STRATEGY.md` → Abschnitt "Troubleshooting"
|
||||
- Change-Management Strategie: `SYNC-STRATEGY.md` → Abschnitt "Change-Management"
|
||||
|
||||
---
|
||||
|
||||
## 🤖 Was das Script tut
|
||||
|
||||
1. Liest alle in `git ls-files` registrierten Dateien
|
||||
2. Vergleicht deren Checksum zwischen Repo und Home
|
||||
3. Erstellt automatisch Backups bei Änderungen
|
||||
4. Synchronisiert basierend auf gewähltem Modus
|
||||
5. Protokolliert alles in `.sync-home-content.log`
|
||||
6. Entfernt alte Backups (> 30 Tage mit `cleanup`)
|
||||
|
||||
---
|
||||
|
||||
## 💬 Fragen?
|
||||
|
||||
Lesen Sie `SYNC-STRATEGY.md` - fast alle Fragen sind dort beantwortet!
|
||||
|
||||
---
|
||||
|
||||
**Viel Erfolg beim Synchronisieren! 🎉**
|
||||
|
||||
@@ -0,0 +1,423 @@
|
||||
# Synchronisierungs-Strategie für home-content
|
||||
|
||||
## Überblick
|
||||
|
||||
Das Script `sync-home-content.sh` synchronisiert Dateien zwischen dem Git-Repository (`home-content/`) und dem echten Home-Verzeichnis (`$HOME`).
|
||||
|
||||
**Schlüsselprinzipien:**
|
||||
- ✓ Nur Dateien sync, die in `git ls-files` versioniert sind
|
||||
- ✓ Content-basierte Erkennung via md5sum (verlässlicher als Timestamps)
|
||||
- ✓ Automatische Backups bei Änderungen (`.sync-backups/`)
|
||||
- ✓ Mehrere Modi für verschiedene Szenarien
|
||||
- ✓ Sicher via Dry-Run vor echten Änderungen
|
||||
|
||||
---
|
||||
|
||||
## Modi & Anwendungsfälle
|
||||
|
||||
### 1. **STATUS** (Standard) — Nur Information
|
||||
```bash
|
||||
./sync-home-content.sh status
|
||||
./sync-home-content.sh status -v # verbose mit Checksummen
|
||||
```
|
||||
|
||||
**Was es tut:**
|
||||
- Vergleicht alle Dateien im Repo mit Home-Dir
|
||||
- Zeigt Unterschiede via md5sum
|
||||
- **Ändert nichts**
|
||||
|
||||
**Ausgabe-Bedeutungen:**
|
||||
| Symbol | Bedeutung |
|
||||
|--------|-----------|
|
||||
| ✓ | Datei ist identisch |
|
||||
| ≠ | Datei geändert im Home-Dir |
|
||||
| ✚ | Datei nur im Repo (nicht im Home) |
|
||||
|
||||
**Use-Case:** Am Anfang, um zu sehen, was sich geändert hat
|
||||
|
||||
---
|
||||
|
||||
### 2. **PUSH** — Repo → Home-Dir
|
||||
```bash
|
||||
./sync-home-content.sh push --dry-run # Erst testen
|
||||
./sync-home-content.sh push # Echte Synchronisierung
|
||||
```
|
||||
|
||||
**Was es tut:**
|
||||
- Kopiert Dateien vom Repo ins Home-Dir
|
||||
- Überschreibt lokale Änderungen ohne zu fragen
|
||||
- Erstellt Backup von geänderten lokalen Dateien (`.sync-backups/`)
|
||||
- Neue Dateien: einfach kopieren ohne Backup
|
||||
|
||||
**Ablauf:**
|
||||
```
|
||||
1. Status 0 (identisch): unverändert
|
||||
2. Status 3 (geändert): Backup Home → Repo → Home (Repo gewinnt)
|
||||
3. Status 4 (nur Repo): Kopieren ohne Backup
|
||||
```
|
||||
|
||||
**Use-Case:**
|
||||
- Repo-Dateien sind authoritative Version (z.B. nach Git-Pull)
|
||||
- Lokale Änderungen waren Fehlgriffe
|
||||
- Schnelle Synchronisierung nach `.gitconfig` Update
|
||||
|
||||
---
|
||||
|
||||
### 3. **PULL** — Home-Dir → Repo
|
||||
```bash
|
||||
./sync-home-content.sh pull --dry-run # Erst testen
|
||||
./sync-home-content.sh pull # Echte Synchronisierung
|
||||
```
|
||||
|
||||
**Was es tut:**
|
||||
- Kopiert veränderte Dateien vom Home-Dir ins Repo
|
||||
- Nur Updates bei geänderten Dateien
|
||||
- Erstellt Backup der Repo-Dateien vor Update
|
||||
- Nur im Home existierende Dateien: ignoriert
|
||||
|
||||
**Ablauf:**
|
||||
```
|
||||
1. Status 0 (identisch): unverändert
|
||||
2. Status 3 (geändert): Backup Repo → Home → Repo (Home gewinnt)
|
||||
3. Status 4 (nur Repo): ignoriert (nicht im Home)
|
||||
```
|
||||
|
||||
**Use-Case:**
|
||||
- Lokale Änderungen sind wichtig (z.B. neue `.gitconfig`)
|
||||
- Diese sollen ins Repo → für andere Maschinen verfügbar machen
|
||||
- Git-Commit erforderlich nach Pull
|
||||
|
||||
---
|
||||
|
||||
### 4. **SYNC** — Bidirektional (Klug)
|
||||
```bash
|
||||
./sync-home-content.sh sync --dry-run # Testen
|
||||
./sync-home-content.sh sync # Auto-Konflikt-Lösung
|
||||
./sync-home-content.sh sync --interactive # Fragen bei Konflikten
|
||||
```
|
||||
|
||||
**Was es tut:**
|
||||
- Bidirektionale Synchronisierung
|
||||
- **Automatisch:** Neuere Datei gewinnt (via Timestamp)
|
||||
- **Interaktiv:** Benutzer wählt bei jedem Konflikt
|
||||
|
||||
**Konflikt-Handling (Non-Interactive):**
|
||||
```
|
||||
Wenn beide unterschiedlich:
|
||||
- Home neuerer (mtime) → Home gewinnt (→ Repo)
|
||||
- Repo neuerer (mtime) → Repo gewinnt (→ Home)
|
||||
```
|
||||
|
||||
**Konflikt-Handling (Interactive):**
|
||||
```
|
||||
Optionen für jede konflikt-Datei:
|
||||
1) Nehme Repo-Version (→ Home überschreiben)
|
||||
2) Nehme Home-Version (← Repo überschreiben)
|
||||
3) Behalte beide (Home als Backup aufbewahren)
|
||||
4) Überspringe diese Datei
|
||||
```
|
||||
|
||||
**Beispiel Workflow:**
|
||||
```bash
|
||||
# 1. Anschauen, was zu sync ist
|
||||
./sync-home-content.sh status -v
|
||||
|
||||
# 2. Sicher testen
|
||||
./sync-home-content.sh sync --dry-run
|
||||
|
||||
# 3. Interaktiv bei Konflikten
|
||||
./sync-home-content.sh sync --interactive
|
||||
|
||||
# 4. Backups prüfen
|
||||
ls -lh .sync-backups/
|
||||
```
|
||||
|
||||
**Use-Case:**
|
||||
- Routine-Sync mit potentiellen lokalen Änderungen
|
||||
- Sicherheit durch Backups
|
||||
- Smart: neuere Versionen gewinnen automatisch
|
||||
|
||||
---
|
||||
|
||||
### 5. **CLEANUP** — Alte Backups löschen
|
||||
```bash
|
||||
./sync-home-content.sh cleanup
|
||||
```
|
||||
|
||||
**Was es tut:**
|
||||
- Löscht Backups älter als 30 Tage
|
||||
- Spart Speicherplatz
|
||||
|
||||
**Backup-Struktur:**
|
||||
```
|
||||
.sync-backups/
|
||||
├── .gitconfig.20260928_150000.backup
|
||||
├── .gitconfig.20260925_140000.backup ← älter als 30 Tage → löschen
|
||||
├── .zshrc.20260927_180000.backup
|
||||
└── ...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 6. **LIST** — Zeige verwaltete Dateien
|
||||
```bash
|
||||
./sync-home-content.sh list
|
||||
```
|
||||
|
||||
Gibt alle Dateien aus, die versioniert sind (`git ls-files`).
|
||||
|
||||
---
|
||||
|
||||
## Change-Management Strategie
|
||||
|
||||
### Inhalt vs. Timestamp?
|
||||
|
||||
Das Script nutzt **Content-Vergleich (md5sum)** als Primär-Verfahren:
|
||||
|
||||
| Ansatz | Vorteile | Nachteile |
|
||||
|--------|----------|----------|
|
||||
| **Checksum (md5)** | Erkennt wirkliche Änderungen, Zeitzone-unabhängig | Minimal langsamer |
|
||||
| **Timestamp** | Schnell | Falsch-Positive bei cp/rsync, Zeitzone-sensibel |
|
||||
|
||||
**Strategie:**
|
||||
1. **Erkennung:** md5sum → schnelle, zuverlässige Erkennung echter Änderungen
|
||||
2. **Konflikt-Auflösung:** Timestamp (`mtime`) → welche Version ist neuerer
|
||||
|
||||
---
|
||||
|
||||
## Backup-Strategie
|
||||
|
||||
### Automatische Backups
|
||||
- **Bei Push:** Backup der lokalen (überschriebenen) Datei vor Update
|
||||
- **Bei Pull:** Backup der Repo-Datei vor Update
|
||||
- **Bei Sync:** Backup je nach Konflikt-Lösung
|
||||
- **Deaktivierbar:** `--no-backup` Option
|
||||
|
||||
### Backup-Verzeichnis
|
||||
```bash
|
||||
.sync-backups/
|
||||
├── .gitconfig.20260928_150000.backup # Timestamp = YYYYMMDD_HHMMSS
|
||||
├── .gitconfig.20260925_200000.backup
|
||||
└── .zshrc.20260927_120000.backup
|
||||
```
|
||||
|
||||
### Restore aus Backup
|
||||
```bash
|
||||
# Beispiel: .gitconfig wiederherstellen
|
||||
cp .sync-backups/.gitconfig.20260928_150000.backup home-content/.gitconfig
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Workflow-Beispiele
|
||||
|
||||
### Scenario 1: Neue `.gitconfig` lokal
|
||||
```bash
|
||||
# 1. Bearbeite lokal im Home
|
||||
vim ~/.gitconfig
|
||||
|
||||
# 2. Check Status
|
||||
./sync-home-content.sh status
|
||||
# Output: ≠ geändert im Home: .gitconfig
|
||||
|
||||
# 3. Ins Repo synchronisieren
|
||||
./sync-home-content.sh pull --dry-run
|
||||
# Output: ← update: .gitconfig (Home → Repo)
|
||||
|
||||
./sync-home-content.sh pull
|
||||
# Output: Backup erstellt: .gitconfig (vor Pull) → .sync-backups/.gitconfig.20260928_XXX
|
||||
|
||||
# 4. Git-Commit
|
||||
cd home-content
|
||||
git diff .gitconfig
|
||||
git add .gitconfig
|
||||
git commit -m "chore: update .gitconfig"
|
||||
git push
|
||||
```
|
||||
|
||||
### Scenario 2: Repo-Update von anderer Maschine
|
||||
```bash
|
||||
# 1. Remote fetch (Git Pull)
|
||||
git pull origin main
|
||||
|
||||
# 2. Check Status
|
||||
./sync-home-content.sh status
|
||||
# Output: ≠ geändert im Home: .zshrc
|
||||
|
||||
# 3. Repo-Version ins Home
|
||||
./sync-home-content.sh push --dry-run
|
||||
# Output: → update: .zshrc (Repo → Home) [lokale Änderung wird überschrieben]
|
||||
|
||||
./sync-home-content.sh push
|
||||
# Output: Backup erstellt: .zshrc (vor Push) → .sync-backups/.zshrc.20260928_XXX
|
||||
|
||||
# 4. Neue Datei aktiv (Shell reload bei .zshrc)
|
||||
source ~/.zshrc
|
||||
```
|
||||
|
||||
### Scenario 3: Bidirektional mit Konflikten
|
||||
```bash
|
||||
./sync-home-content.sh sync --interactive
|
||||
# Für jede Konflikt-Datei: interaktiv wählen
|
||||
|
||||
# Oder Auto-Modus (neuere gewinnt)
|
||||
./sync-home-content.sh sync
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Optionen Referenz
|
||||
|
||||
| Option | Effekt | Beispiel |
|
||||
|--------|--------|---------|
|
||||
| `-d`, `--dry-run` | Zeige nur, ohne zu ändern | `./sync status --dry-run` |
|
||||
| `-v`, `--verbose` | Debug-Output (mit Checksummen) | `./sync status -v` |
|
||||
| `-i`, `--interactive` | Frage bei Konflikten (nur sync) | `./sync sync --interactive` |
|
||||
| `--no-backup` | Keine Backups erstellen | `./sync push --no-backup` |
|
||||
| `-h`, `--help` | Zeige Hilfe | `./sync -h` |
|
||||
|
||||
**Kombinierbar:**
|
||||
```bash
|
||||
./sync-home-content.sh sync --dry-run --verbose --interactive
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Logs & Debugging
|
||||
|
||||
### Log-Datei
|
||||
Alle Operationen werden protokolliert in `.sync-home-content.log`:
|
||||
```bash
|
||||
tail -f .sync-home-content.log
|
||||
```
|
||||
|
||||
### Verbose Debug-Output
|
||||
```bash
|
||||
./sync-home-content.sh status -v
|
||||
```
|
||||
|
||||
Output zeigt:
|
||||
- Checksummen für jede Datei
|
||||
- Genaue Änderungstypen
|
||||
- Schritt-für-Schritt Durchsatz
|
||||
|
||||
---
|
||||
|
||||
## Best Practices
|
||||
|
||||
### ✓ TUN:
|
||||
1. **Vor kritischen Änderungen:** `status` checken
|
||||
2. **Vor echtem Sync:** `--dry-run` testen
|
||||
3. **Periodisch Backups prüfen:** `ls -lh .sync-backups/`
|
||||
4. **Nach Push:** Git-Commit & Push (falls Repo-Änderungen)
|
||||
5. **Verbose nutzen:** Bei Unsicherheiten `-v` Option
|
||||
|
||||
### ✗ NICHT:
|
||||
1. `--no-backup` ohne Grund nutzen (Backups sind Rettungsanker)
|
||||
2. `push` Mode als Standard (zu aggressiv)
|
||||
3. Logs löschen ohne Archivierung
|
||||
4. Alte Backups manuell löschen (dafür `cleanup`)
|
||||
5. Mehrere Sync-Prozesse parallel laufen lassen
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Problem: "git: command not found"
|
||||
```bash
|
||||
# Prüfe ob in Repository:
|
||||
pwd
|
||||
# Sollte: /Users/u241100/mac-home
|
||||
|
||||
# Prüfe git Status:
|
||||
git status
|
||||
```
|
||||
|
||||
### Problem: "Permission denied" auf Backup
|
||||
```bash
|
||||
# Prüfe .sync-backups Permissions:
|
||||
ls -ld .sync-backups
|
||||
chmod 755 .sync-backups
|
||||
chmod 644 .sync-backups/*
|
||||
```
|
||||
|
||||
### Problem: Datei wurde falsch überschrieben
|
||||
```bash
|
||||
# 1. Finde richtiges Backup
|
||||
ls .sync-backups/ | grep dateiname
|
||||
|
||||
# 2. Restore
|
||||
cp .sync-backups/dateiname.YYYYMMDD_HHMMSS.backup home-content/dateiname
|
||||
|
||||
# 3. Ggf. manual zurückschreiben nach Home
|
||||
cp home-content/dateiname ~/dateiname
|
||||
```
|
||||
|
||||
### Problem: Script ist zu langsam
|
||||
- Meist normal (für 14 Dateien < 1 Sek)
|
||||
- Bei Verzeichniss-Inhalten mit vielen Dateien: md5sum ist minimal-overhead
|
||||
|
||||
---
|
||||
|
||||
## Integration in Workflow
|
||||
|
||||
### Alias für schnellen Zugriff
|
||||
```bash
|
||||
# In ~/.zshrc hinzufügen:
|
||||
alias synchome="~/mac-home/sync-home-content.sh"
|
||||
alias synchome-status="~/mac-home/sync-home-content.sh status"
|
||||
alias synchome-pull="~/mac-home/sync-home-content.sh pull --dry-run && ~/mac-home/sync-home-content.sh pull"
|
||||
```
|
||||
|
||||
### Pre-Commit Hook (Optional)
|
||||
```bash
|
||||
# .git/hooks/pre-commit
|
||||
#!/bin/bash
|
||||
~/mac-home/sync-home-content.sh status
|
||||
# Bricht ab, wenn Unterschiede existieren
|
||||
```
|
||||
|
||||
### Cron-Job für regelmäßigen Sync
|
||||
```bash
|
||||
# Jeden Tag um 2 Uhr nachts
|
||||
0 2 * * * cd ~/mac-home && ./sync-home-content.sh sync >> /tmp/sync-home.log 2>&1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Zusammenfassung Konflikt-Handling
|
||||
|
||||
| Szenario | Pull | Push | Sync (Auto) | Sync (Interactive) |
|
||||
|----------|------|------|-------------|-------------------|
|
||||
| Datei identisch | — | — | — | — |
|
||||
| Nur Home geändert | Home gewinnt | — | neuere (Home) gewinnt | Benutzer wählt |
|
||||
| Nur Repo geändert | — | Repo gewinnt | neuere (Repo) gewinnt | Benutzer wählt |
|
||||
| Beide geändert | — | — | neuere (Timestamp) gewinnt | Benutzer wählt (4 Optionen) |
|
||||
| Nur im Repo | ignoriert | kopiert | kopiert | kopiert |
|
||||
|
||||
---
|
||||
|
||||
## Checkliste für neuen Rechner
|
||||
|
||||
```bash
|
||||
cd ~/mac-home
|
||||
|
||||
# 1. Status prüfen
|
||||
./sync-home-content.sh status
|
||||
|
||||
# 2. Neue Dateien trocken kopieren
|
||||
./sync-home-content.sh push --dry-run
|
||||
|
||||
# 3. Echte Synchronisierung
|
||||
./sync-home-content.sh push
|
||||
|
||||
# 4. Backups überprüfen (sollten leer sein)
|
||||
ls -la .sync-backups/
|
||||
|
||||
# 5. Log prüfen
|
||||
tail .sync-home-content.log
|
||||
```
|
||||
|
||||
Fertig! Home-Verzeichnis ist jetzt mit Repository sync.
|
||||
|
||||
|
||||
Executable
+539
@@ -0,0 +1,539 @@
|
||||
#!/bin/bash
|
||||
|
||||
################################################################################
|
||||
# Synchronisierungs-Script: mac-home/home-content <-> Home-Directory
|
||||
#
|
||||
# Synchronisiert nur die Dateien, die im Git-Repo versioniert sind.
|
||||
# Unterstützt mehrere Modi mit Konflikt-Handling.
|
||||
#
|
||||
# Strategie bei Changes:
|
||||
# - Content-basiert via md5sum (verlässlicher als Timestamp)
|
||||
# - Automatische Backups bei lokalen Änderungen
|
||||
# - Mehrere Modi für verschiedene Szenarien
|
||||
################################################################################
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Farben
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Verzeichnisse
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_DIR="$SCRIPT_DIR/home-content"
|
||||
HOME_DIR="$HOME"
|
||||
BACKUP_DIR="$SCRIPT_DIR/.sync-backups"
|
||||
LOG_FILE="$SCRIPT_DIR/.sync-home-content.log"
|
||||
|
||||
# Konfiguration
|
||||
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
||||
DRY_RUN=false
|
||||
VERBOSE=false
|
||||
INTERACTIVE=false
|
||||
AUTO_BACKUP=true
|
||||
|
||||
################################################################################
|
||||
# Hilfsfunktionen
|
||||
################################################################################
|
||||
|
||||
log() {
|
||||
echo -e "${BLUE}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} $*" | tee -a "$LOG_FILE"
|
||||
}
|
||||
|
||||
error() {
|
||||
echo -e "${RED}[ERROR]${NC} $*" >&2 | tee -a "$LOG_FILE"
|
||||
}
|
||||
|
||||
success() {
|
||||
echo -e "${GREEN}[OK]${NC} $*" | tee -a "$LOG_FILE"
|
||||
}
|
||||
|
||||
warn() {
|
||||
echo -e "${YELLOW}[WARN]${NC} $*" | tee -a "$LOG_FILE"
|
||||
}
|
||||
|
||||
verbose() {
|
||||
[[ "$VERBOSE" == true ]] && echo -e "${BLUE}[DEBUG]${NC} $*" | tee -a "$LOG_FILE"
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Berechne md5sum für eine Datei (mit Fallback für verschiedene OSs)
|
||||
################################################################################
|
||||
|
||||
get_checksum() {
|
||||
local file="$1"
|
||||
if [[ -f "$file" ]]; then
|
||||
if command -v md5 &> /dev/null; then
|
||||
# macOS
|
||||
md5 -q "$file"
|
||||
elif command -v md5sum &> /dev/null; then
|
||||
# Linux
|
||||
md5sum "$file" | awk '{print $1}'
|
||||
else
|
||||
error "Weder md5 noch md5sum verfügbar"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Erstelle Backup einer Datei
|
||||
################################################################################
|
||||
|
||||
backup_file() {
|
||||
local src="$1"
|
||||
local desc="$2"
|
||||
|
||||
[[ ! -f "$src" ]] && return 0
|
||||
|
||||
mkdir -p "$BACKUP_DIR"
|
||||
local backup_file="$BACKUP_DIR/$(basename "$src").$TIMESTAMP.backup"
|
||||
cp "$src" "$backup_file"
|
||||
log "Backup erstellt: $desc → $backup_file"
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Status einer Datei prüfen
|
||||
################################################################################
|
||||
|
||||
# Vergleicht Datei im Repo mit Home-Dir
|
||||
# Returns:
|
||||
# 0 = identisch
|
||||
# 1 = nur in Repo
|
||||
# 2 = nur im Home
|
||||
# 3 = unterschiedlicher Inhalt
|
||||
# 4 = nur im Repo, nicht im Home
|
||||
|
||||
check_file_status() {
|
||||
local repo_file="$1"
|
||||
local home_file="$2"
|
||||
local repo_name=$(basename "$repo_file")
|
||||
|
||||
if [[ ! -f "$repo_file" ]]; then
|
||||
return 1 # nicht im Repo
|
||||
fi
|
||||
|
||||
if [[ ! -f "$home_file" ]]; then
|
||||
return 4 # nur im Repo
|
||||
fi
|
||||
|
||||
local repo_sum=$(get_checksum "$repo_file")
|
||||
local home_sum=$(get_checksum "$home_file")
|
||||
|
||||
if [[ "$repo_sum" == "$home_sum" ]]; then
|
||||
return 0 # identisch
|
||||
else
|
||||
return 3 # unterschiedlich
|
||||
fi
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Modus: STATUS
|
||||
# Zeigt Unterschiede zwischen Repo und Home
|
||||
################################################################################
|
||||
|
||||
mode_status() {
|
||||
log "Status: Vergleiche Repo mit Home-Dir..."
|
||||
|
||||
local identical=0
|
||||
local modified=0
|
||||
local repo_only=0
|
||||
|
||||
while IFS= read -r file; do
|
||||
local repo_file="$REPO_DIR/$file"
|
||||
local basename=$(basename "$file")
|
||||
local home_file="$HOME_DIR/$basename"
|
||||
|
||||
check_file_status "$repo_file" "$home_file"
|
||||
local status=$?
|
||||
|
||||
case $status in
|
||||
0)
|
||||
verbose "✓ identisch: $basename"
|
||||
((identical++))
|
||||
;;
|
||||
3)
|
||||
warn "≠ geändert im Home: $basename"
|
||||
if [[ "$VERBOSE" == true ]]; then
|
||||
echo " Repo: $(get_checksum "$repo_file")"
|
||||
echo " Home: $(get_checksum "$home_file")"
|
||||
fi
|
||||
((modified++))
|
||||
;;
|
||||
4)
|
||||
warn "✗ nur im Repo: $basename (nicht im Home)"
|
||||
((repo_only++))
|
||||
;;
|
||||
esac
|
||||
done < <(cd "$REPO_DIR" && git ls-files)
|
||||
|
||||
echo ""
|
||||
success "Status-Zusammenfassung:"
|
||||
echo " Identisch: $identical"
|
||||
echo " Geändert: $modified"
|
||||
echo " Nur im Repo: $repo_only"
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Modus: PULL
|
||||
# Home-Dir → Repo (kopiere geänderte Dateien von Home ins Repo)
|
||||
################################################################################
|
||||
|
||||
mode_pull() {
|
||||
log "Pull: Synchronisiere geänderte Dateien von Home-Dir ins Repo..."
|
||||
|
||||
local updated=0
|
||||
local skipped=0
|
||||
|
||||
while IFS= read -r file; do
|
||||
local repo_file="$REPO_DIR/$file"
|
||||
local basename=$(basename "$file")
|
||||
local home_file="$HOME_DIR/$basename"
|
||||
|
||||
check_file_status "$repo_file" "$home_file"
|
||||
local status=$?
|
||||
|
||||
case $status in
|
||||
0)
|
||||
verbose "⊙ unverändert: $basename"
|
||||
;;
|
||||
3)
|
||||
warn "← update: $basename (Home → Repo)"
|
||||
if [[ "$DRY_RUN" == false ]]; then
|
||||
[[ "$AUTO_BACKUP" == true ]] && backup_file "$repo_file" "$basename (vor Pull)"
|
||||
cp "$home_file" "$repo_file"
|
||||
((updated++))
|
||||
fi
|
||||
;;
|
||||
4)
|
||||
verbose "⊘ ausgelassen: $basename (nicht im Home)"
|
||||
((skipped++))
|
||||
;;
|
||||
esac
|
||||
done < <(cd "$REPO_DIR" && git ls-files)
|
||||
|
||||
success "Pull abgeschlossen: $updated aktualisiert, $skipped ausgelassen"
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Modus: PUSH
|
||||
# Repo → Home (kopiere Repo-Dateien ins Home-Dir)
|
||||
################################################################################
|
||||
|
||||
mode_push() {
|
||||
log "Push: Synchronisiere Repo-Dateien ins Home-Dir..."
|
||||
|
||||
local updated=0
|
||||
local backed_up=0
|
||||
local skipped=0
|
||||
|
||||
while IFS= read -r file; do
|
||||
local repo_file="$REPO_DIR/$file"
|
||||
local basename=$(basename "$file")
|
||||
local home_file="$HOME_DIR/$basename"
|
||||
|
||||
check_file_status "$repo_file" "$home_file"
|
||||
local status=$?
|
||||
|
||||
case $status in
|
||||
0)
|
||||
verbose "⊙ unverändert: $basename"
|
||||
;;
|
||||
3)
|
||||
warn "→ update: $basename (Repo → Home) [lokale Änderung wird überschrieben]"
|
||||
if [[ "$DRY_RUN" == false ]]; then
|
||||
if [[ "$AUTO_BACKUP" == true ]]; then
|
||||
backup_file "$home_file" "$basename (vor Push)"
|
||||
((backed_up++))
|
||||
fi
|
||||
cp "$repo_file" "$home_file"
|
||||
((updated++))
|
||||
fi
|
||||
;;
|
||||
4)
|
||||
verbose "✚ neu: $basename (Repo → Home)"
|
||||
if [[ "$DRY_RUN" == false ]]; then
|
||||
cp "$repo_file" "$home_file"
|
||||
((updated++))
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
done < <(cd "$REPO_DIR" && git ls-files)
|
||||
|
||||
success "Push abgeschlossen: $updated kopiert, $backed_up Backups, $skipped ausgelassen"
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Modus: SYNC (bidirektional mit Konflikt-Handling)
|
||||
################################################################################
|
||||
|
||||
mode_sync() {
|
||||
log "Sync: Bidirektionale Synchronisierung..."
|
||||
|
||||
local updated=0
|
||||
local backed_up=0
|
||||
local conflicts=0
|
||||
|
||||
while IFS= read -r file; do
|
||||
local repo_file="$REPO_DIR/$file"
|
||||
local basename=$(basename "$file")
|
||||
local home_file="$HOME_DIR/$basename"
|
||||
|
||||
check_file_status "$repo_file" "$home_file"
|
||||
local status=$?
|
||||
|
||||
case $status in
|
||||
0)
|
||||
verbose "⊙ unverändert: $basename"
|
||||
;;
|
||||
3)
|
||||
# Konflikt: beide unterschiedlich
|
||||
if [[ "$INTERACTIVE" == true ]]; then
|
||||
echo ""
|
||||
warn "KONFLIKT: $basename unterscheidet sich"
|
||||
echo " Repo Checksum: $(get_checksum "$repo_file")"
|
||||
echo " Home Checksum: $(get_checksum "$home_file")"
|
||||
echo ""
|
||||
echo "Optionen:"
|
||||
echo " 1) Nehme Repo-Version (→ Home überschreiben)"
|
||||
echo " 2) Nehme Home-Version (← Repo überschreiben)"
|
||||
echo " 3) Behalte beide (Home-Version wird gebackupt)"
|
||||
echo " 4) Überspringe diese Datei"
|
||||
read -p "Wahl [1-4]: " choice
|
||||
|
||||
case $choice in
|
||||
1)
|
||||
[[ "$DRY_RUN" == false ]] && {
|
||||
backup_file "$home_file" "$basename (Konflikt-Lösung)"
|
||||
cp "$repo_file" "$home_file"
|
||||
((updated++))
|
||||
}
|
||||
;;
|
||||
2)
|
||||
[[ "$DRY_RUN" == false ]] && {
|
||||
backup_file "$repo_file" "$basename (Konflikt-Lösung)"
|
||||
cp "$home_file" "$repo_file"
|
||||
((updated++))
|
||||
}
|
||||
;;
|
||||
3)
|
||||
[[ "$DRY_RUN" == false ]] && backup_file "$home_file" "$basename (Konflikt-Aufbewahrung)"
|
||||
((backed_up++))
|
||||
;;
|
||||
4)
|
||||
((conflicts++))
|
||||
;;
|
||||
esac
|
||||
else
|
||||
# Non-interactive: Home gewinnt (lokal neuere Version wird bevorzugt)
|
||||
local repo_mtime=$(stat -f%m "$repo_file" 2>/dev/null || stat -c%Y "$repo_file")
|
||||
local home_mtime=$(stat -f%m "$home_file" 2>/dev/null || stat -c%Y "$home_file")
|
||||
|
||||
if (( home_mtime > repo_mtime )); then
|
||||
verbose "← konflikt (Home neuerer): $basename → Repo wird aktualisiert"
|
||||
if [[ "$DRY_RUN" == false ]]; then
|
||||
backup_file "$repo_file" "$basename (Konflikt)"
|
||||
cp "$home_file" "$repo_file"
|
||||
((updated++))
|
||||
fi
|
||||
else
|
||||
verbose "→ konflikt (Repo neuerer): $basename → Home wird aktualisiert"
|
||||
if [[ "$DRY_RUN" == false ]]; then
|
||||
backup_file "$home_file" "$basename (Konflikt)"
|
||||
cp "$repo_file" "$home_file"
|
||||
((updated++))
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
4)
|
||||
verbose "✚ neu: $basename (Repo → Home)"
|
||||
if [[ "$DRY_RUN" == false ]]; then
|
||||
cp "$repo_file" "$home_file"
|
||||
((updated++))
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
done < <(cd "$REPO_DIR" && git ls-files)
|
||||
|
||||
success "Sync abgeschlossen: $updated synchronisiert, $backed_up Backups, $conflicts Konflikte"
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Modus: CLEANUP
|
||||
# Entferne alte Backup-Dateien (älter als 30 Tage)
|
||||
################################################################################
|
||||
|
||||
mode_cleanup() {
|
||||
log "Cleanup: Entferne alte Backups (älter als 30 Tage)..."
|
||||
|
||||
if [[ ! -d "$BACKUP_DIR" ]]; then
|
||||
success "Kein Backup-Verzeichnis vorhanden"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local removed=0
|
||||
while IFS= read -r backup_file; do
|
||||
rm -f "$backup_file"
|
||||
verbose "Gelöscht: $backup_file"
|
||||
((removed++))
|
||||
done < <(find "$BACKUP_DIR" -type f -mtime +30)
|
||||
|
||||
success "Cleanup abgeschlossen: $removed alte Backups gelöscht"
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Modus: LIST
|
||||
# Liste alle verwalteten Dateien auf
|
||||
################################################################################
|
||||
|
||||
mode_list() {
|
||||
log "Liste alle verwalteten Dateien:"
|
||||
echo ""
|
||||
cd "$REPO_DIR" && git ls-files | while read -r file; do
|
||||
echo " • $file"
|
||||
done
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Hilfefunktion
|
||||
################################################################################
|
||||
|
||||
show_help() {
|
||||
cat << EOF
|
||||
Verwendung: $0 [MODE] [OPTIONS]
|
||||
|
||||
MODI:
|
||||
status Zeige Unterschiede zwischen Repo und Home-Dir (Standard)
|
||||
pull Synchronisiere von Home-Dir ins Repo (Home → Repo)
|
||||
push Synchronisiere vom Repo ins Home-Dir (Repo → Home)
|
||||
sync Bidirektionale Synchronisierung mit Konflikt-Handling
|
||||
cleanup Entferne alte Backups (älter als 30 Tage)
|
||||
list Liste alle verwalteten Dateien auf
|
||||
|
||||
OPTIONEN:
|
||||
-d, --dry-run Zeige nur Änderungen, ohne zu modifizieren
|
||||
-v, --verbose Verbose Output (DEBUG)
|
||||
-i, --interactive Interaktive Konflikte lösen (nur für sync)
|
||||
--no-backup Keine automatischen Backups erstellen
|
||||
-h, --help Diese Hilfe anzeigen
|
||||
|
||||
BEISPIELE:
|
||||
# Status anzeigen
|
||||
$0 status
|
||||
|
||||
# Von Home ins Repo synchronisieren (Trockentest)
|
||||
$0 pull --dry-run
|
||||
|
||||
# Bidirektional mit Backup synchronisieren
|
||||
$0 sync
|
||||
|
||||
# Interaktiv mit Konflikt-Handling
|
||||
$0 sync --interactive
|
||||
|
||||
STRATEGIE:
|
||||
• Content-basiert via md5sum (zuverlässiger als Timestamps)
|
||||
• Automatische Backups in .sync-backups/ vor Änderungen
|
||||
• Nur Dateien synchronisieren, die in git versioniert sind
|
||||
• Logs in .sync-home-content.log
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Hauptprogramm
|
||||
################################################################################
|
||||
|
||||
main() {
|
||||
local mode="status"
|
||||
|
||||
# Parse Argumente
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
status|pull|push|sync|cleanup|list)
|
||||
mode="$1"
|
||||
shift
|
||||
;;
|
||||
-d|--dry-run)
|
||||
DRY_RUN=true
|
||||
shift
|
||||
;;
|
||||
-v|--verbose)
|
||||
VERBOSE=true
|
||||
shift
|
||||
;;
|
||||
-i|--interactive)
|
||||
INTERACTIVE=true
|
||||
shift
|
||||
;;
|
||||
--no-backup)
|
||||
AUTO_BACKUP=false
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
show_help
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
error "Unbekannte Option: $1"
|
||||
show_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Validierungen
|
||||
if [[ ! -d "$REPO_DIR" ]]; then
|
||||
error "Repo-Verzeichnis nicht gefunden: $REPO_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! git -C "$REPO_DIR" rev-parse --git-dir > /dev/null 2>&1; then
|
||||
error "$REPO_DIR ist kein Git-Repository"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Header
|
||||
log "═══════════════════════════════════════════════════════════"
|
||||
log "Modus: $mode"
|
||||
[[ "$DRY_RUN" == true ]] && log "DRY-RUN: Keine Änderungen werden vorgenommen"
|
||||
[[ "$INTERACTIVE" == true ]] && log "INTERAKTIV: Bei Konflikten wird nachgefragt"
|
||||
log "═══════════════════════════════════════════════════════════"
|
||||
|
||||
# Führe Modus aus
|
||||
case $mode in
|
||||
status)
|
||||
mode_status
|
||||
;;
|
||||
pull)
|
||||
mode_pull
|
||||
;;
|
||||
push)
|
||||
mode_push
|
||||
;;
|
||||
sync)
|
||||
mode_sync
|
||||
;;
|
||||
cleanup)
|
||||
mode_cleanup
|
||||
;;
|
||||
list)
|
||||
mode_list
|
||||
;;
|
||||
*)
|
||||
error "Unbekannter Modus: $mode"
|
||||
show_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
log "═══════════════════════════════════════════════════════════"
|
||||
[[ "$DRY_RUN" == true ]] && success "DRY-RUN abgeschlossen (keine Änderungen)" || success "Abgeschlossen"
|
||||
}
|
||||
|
||||
# Starte Script
|
||||
main "$@"
|
||||
|
||||
Reference in new issue
Block a user