Save before creating restore point: Before implementing auto-commit system

Auto-saved at 2025-07-29 14:24:49

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Docker Config Backup
2025-07-29 14:24:49 +02:00
parent 0ead94ac8d
commit 58eb8c169b
4 changed files with 467 additions and 2 deletions

174
AUTO-COMMIT-README.md Normal file
View File

@@ -0,0 +1,174 @@
# Auto-Commit System for Timeshift Project
This system automatically saves your work to git to prevent losing changes when Claude gets restarted or when making experimental changes.
## 🚀 Quick Start
### Start Auto-Watch (Recommended)
```bash
npm run watch-commit
```
This will automatically commit changes every 30 seconds when files are modified.
### Manual Commands
```bash
# Save current work immediately
npm run save "Your commit message"
# Create a restore point before major changes
npm run restore-point "Before major refactor"
# List all restore points
./auto-commit.sh list
# Clean old restore points (keeps last 10)
./auto-commit.sh cleanup
```
## 📋 How It Works
### Automatic Commits
- **File Watcher**: Monitors `components/`, `app/`, `lib/`, `styles/` directories
- **Smart Delay**: Waits 30 seconds after last change before committing
- **Rate Limiting**: Max 10 commits per hour to avoid spam
- **File Types**: Watches `.tsx`, `.ts`, `.js`, `.jsx`, `.css`, `.scss`, `.json` files
### Restore Points
- **Branches**: Creates timestamped branches like `restore-point-20250129-143022`
- **Automatic**: Creates restore points on startup and every 30 minutes
- **Manual**: Create before risky changes with `npm run restore-point "description"`
## 🔧 Features
### Auto-Commit Script Features
✅ Automatic timestamped commits
✅ Descriptive commit messages
✅ Rate limiting to prevent spam
✅ Restore point creation
✅ Cleanup of old restore points
✅ Git status checking
### File Watcher Features
✅ Real-time file monitoring
✅ Smart batching of changes
✅ Graceful shutdown handling
✅ Periodic restore points
✅ Console logging for transparency
## 📚 Usage Examples
### Starting Your Work Session
```bash
# Start the auto-commit watcher
npm run watch-commit
# In another terminal, start development
npm run dev
```
### Before Making Risky Changes
```bash
# Create a restore point
npm run restore-point "Before implementing new feature"
# Make your changes...
# Files are auto-committed as you work
# If something breaks, restore with:
git checkout restore-point-20250129-143022
```
### Manual Saves
```bash
# Quick save
npm run save
# Save with custom message
npm run save "Fixed spreadsheet column alignment"
```
### Managing Restore Points
```bash
# List all restore points
./auto-commit.sh list
# Clean up old ones (keeps last 10)
./auto-commit.sh cleanup
```
## 🎯 Benefits
1. **Never Lose Work**: Changes are saved every 30 seconds automatically
2. **Easy Recovery**: Restore points let you go back to working states
3. **Experiment Safely**: Try changes knowing you can always revert
4. **Claude Restarts**: No more losing progress when Claude session ends
5. **Version History**: Full git history of all changes with timestamps
## ⚙️ Configuration
### Modify Watch Settings
Edit `watch-and-commit.js`:
```javascript
const COMMIT_DELAY = 30000; // 30 seconds
const MAX_COMMITS_PER_HOUR = 10;
const WATCH_DIRS = ['components', 'app', 'lib', 'styles'];
```
### Modify Auto-Commit Behavior
Edit `auto-commit.sh` to change commit message format or add custom logic.
## 🛟 Recovery Scenarios
### Claude Gets Restarted
Your work is automatically saved! Just continue from where you left off.
### Experimental Changes Break Things
```bash
# List restore points to find a good one
./auto-commit.sh list
# Checkout the restore point
git checkout restore-point-20250129-143022
# Or continue from main with your auto-commits
git checkout main
git log --oneline -10 # See recent auto-commits
```
### Need to Go Back a Few Commits
```bash
# See recent commits
git log --oneline -10
# Reset to a specific commit (keep files)
git reset --soft HEAD~3
# Or create a new branch from specific commit
git checkout -b fix-attempt abc1234
```
## 🚦 Status Indicators
The watcher shows:
- 🔍 **Started**: Auto-commit watcher is running
- 📝 **File changed**: A file was modified
- 🔄 **Performing auto-commit**: About to save changes
-**Auto-commit successful**: Changes saved
- 🔖 **Creating restore point**: Making a backup branch
- ⏸️ **Rate limit reached**: Too many commits, pausing
## 🎮 Quick Reference
| Command | Purpose |
|---------|---------|
| `npm run watch-commit` | Start automatic file watching |
| `npm run save` | Immediate manual commit |
| `npm run restore-point` | Create backup branch |
| `./auto-commit.sh list` | Show restore points |
| `./auto-commit.sh cleanup` | Remove old restore points |
| `git checkout restore-point-XXXXXX` | Restore to backup |
| `git log --oneline -10` | See recent commits |
---
**Pro Tip**: Always run `npm run watch-commit` when starting work with Claude to ensure nothing gets lost! 🛡️

106
auto-commit.sh Executable file
View File

@@ -0,0 +1,106 @@
#!/bin/bash
# Auto-commit script for timeshift project
# Usage: ./auto-commit.sh [message]
set -e
# Function to auto-commit changes
auto_commit() {
local message="$1"
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
# Check if there are any changes
if [[ -n $(git status --porcelain) ]]; then
echo "🔄 Auto-committing changes at $timestamp"
# Add all changes
git add .
# Create commit message
if [[ -z "$message" ]]; then
message="Auto-commit: Save work in progress"
fi
# Commit with timestamp
git commit -m "$(cat <<EOF
$message
Auto-saved at $timestamp
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
EOF
)"
echo "✅ Changes committed successfully"
# Show short log
git log --oneline -3
else
echo "📝 No changes to commit at $timestamp"
fi
}
# Function to create a safe restore point
create_restore_point() {
local description="$1"
local branch_name="restore-point-$(date '+%Y%m%d-%H%M%S')"
echo "🔖 Creating restore point: $branch_name"
# Commit current changes first
auto_commit "Save before creating restore point: $description"
# Create a new branch as restore point
git branch "$branch_name"
echo "✅ Restore point created: $branch_name"
echo "📋 To restore later, run: git checkout $branch_name"
}
# Function to show available restore points
list_restore_points() {
echo "📋 Available restore points:"
git branch | grep "restore-point-" | sed 's/^..//' | sort -r
}
# Function to clean old restore points (keep last 10)
cleanup_restore_points() {
echo "🧹 Cleaning old restore points (keeping last 10)..."
git branch | grep "restore-point-" | sed 's/^..//' | sort -r | tail -n +11 | while read branch; do
git branch -D "$branch" 2>/dev/null && echo "🗑️ Deleted old restore point: $branch"
done
}
# Main script logic
case "$1" in
"commit")
auto_commit "$2"
;;
"restore-point")
create_restore_point "$2"
;;
"list")
list_restore_points
;;
"cleanup")
cleanup_restore_points
;;
*)
echo "📚 Auto-commit utility for timeshift project"
echo ""
echo "Usage:"
echo " $0 commit [message] - Auto-commit current changes"
echo " $0 restore-point [desc] - Create a restore point branch"
echo " $0 list - List available restore points"
echo " $0 cleanup - Clean old restore points"
echo ""
echo "Examples:"
echo " $0 commit 'Fixed spreadsheet layout'"
echo " $0 restore-point 'Before major refactor'"
echo ""
auto_commit "$1"
;;
esac

View File

@@ -6,7 +6,11 @@
"dev": "next dev", "dev": "next dev",
"build": "next build", "build": "next build",
"start": "next start", "start": "next start",
"lint": "next lint" "lint": "next lint",
"auto-commit": "./auto-commit.sh",
"watch-commit": "node watch-and-commit.js",
"save": "./auto-commit.sh commit",
"restore-point": "./auto-commit.sh restore-point"
}, },
"dependencies": { "dependencies": {
"@radix-ui/react-dialog": "^1.1.14", "@radix-ui/react-dialog": "^1.1.14",

181
watch-and-commit.js Executable file
View File

@@ -0,0 +1,181 @@
#!/usr/bin/env node
const fs = require('fs');
const path = require('path');
const { exec } = require('child_process');
const { promisify } = require('util');
const execAsync = promisify(exec);
// Configuration
const WATCH_DIRS = ['components', 'app', 'lib', 'styles'];
const WATCH_EXTENSIONS = ['.tsx', '.ts', '.js', '.jsx', '.css', '.scss', '.json'];
const COMMIT_DELAY = 30000; // 30 seconds delay before auto-commit
const MAX_COMMITS_PER_HOUR = 10;
class AutoCommitWatcher {
constructor() {
this.commitQueue = new Set();
this.commitTimeout = null;
this.commitsThisHour = 0;
this.lastCommitTime = 0;
// Reset commit counter every hour
setInterval(() => {
this.commitsThisHour = 0;
}, 3600000);
console.log('🔍 Auto-commit watcher started');
console.log(`📁 Watching directories: ${WATCH_DIRS.join(', ')}`);
console.log(`⏱️ Commit delay: ${COMMIT_DELAY/1000}s`);
console.log(`🚦 Max commits per hour: ${MAX_COMMITS_PER_HOUR}`);
}
start() {
WATCH_DIRS.forEach(dir => {
const fullPath = path.join(process.cwd(), dir);
if (fs.existsSync(fullPath)) {
this.watchDirectory(fullPath);
console.log(`👀 Watching: ${fullPath}`);
} else {
console.log(`⚠️ Directory not found: ${fullPath}`);
}
});
}
watchDirectory(dirPath) {
try {
fs.watch(dirPath, { recursive: true }, (eventType, filename) => {
if (!filename) return;
const filePath = path.join(dirPath, filename);
const ext = path.extname(filename);
// Check if file extension is in our watch list
if (WATCH_EXTENSIONS.includes(ext)) {
this.handleFileChange(filePath, eventType);
}
});
} catch (error) {
console.error(`❌ Error watching directory ${dirPath}:`, error.message);
}
}
handleFileChange(filePath, eventType) {
const relativePath = path.relative(process.cwd(), filePath);
console.log(`📝 File changed: ${relativePath} (${eventType})`);
// Add to commit queue
this.commitQueue.add(relativePath);
// Clear existing timeout and set new one
if (this.commitTimeout) {
clearTimeout(this.commitTimeout);
}
this.commitTimeout = setTimeout(() => {
this.performAutoCommit();
}, COMMIT_DELAY);
}
async performAutoCommit() {
// Rate limiting
if (this.commitsThisHour >= MAX_COMMITS_PER_HOUR) {
console.log(`⏸️ Rate limit reached (${MAX_COMMITS_PER_HOUR} commits/hour). Skipping auto-commit.`);
this.commitQueue.clear();
return;
}
// Check if enough time has passed since last commit
const now = Date.now();
if (now - this.lastCommitTime < COMMIT_DELAY) {
console.log('⏸️ Too soon since last commit. Skipping.');
return;
}
if (this.commitQueue.size === 0) {
console.log('📋 No files in commit queue');
return;
}
try {
// Check if there are actually changes to commit
const { stdout: status } = await execAsync('git status --porcelain');
if (!status.trim()) {
console.log('📝 No actual changes to commit');
this.commitQueue.clear();
return;
}
console.log('🔄 Performing auto-commit...');
// Create commit message with changed files
const changedFiles = Array.from(this.commitQueue).slice(0, 5); // Limit to 5 files in message
const fileList = changedFiles.join(', ');
const moreFiles = this.commitQueue.size > 5 ? ` and ${this.commitQueue.size - 5} more` : '';
const message = `Auto-save: Updated ${fileList}${moreFiles}`;
// Use our auto-commit script
await execAsync(`./auto-commit.sh commit "${message}"`);
console.log('✅ Auto-commit successful');
this.commitsThisHour++;
this.lastCommitTime = now;
this.commitQueue.clear();
} catch (error) {
console.error('❌ Auto-commit failed:', error.message);
}
}
async createRestorePoint(description = 'Auto restore point') {
try {
console.log('🔖 Creating restore point...');
await execAsync(`./auto-commit.sh restore-point "${description}"`);
console.log('✅ Restore point created');
} catch (error) {
console.error('❌ Failed to create restore point:', error.message);
}
}
}
// Handle process termination gracefully
process.on('SIGINT', async () => {
console.log('\n🛑 Stopping auto-commit watcher...');
// Perform final commit if there are pending changes
try {
const { stdout: status } = await execAsync('git status --porcelain');
if (status.trim()) {
console.log('💾 Saving final changes...');
await execAsync('./auto-commit.sh commit "Final auto-save before shutdown"');
}
} catch (error) {
console.error('❌ Error during shutdown save:', error.message);
}
console.log('👋 Auto-commit watcher stopped');
process.exit(0);
});
// Start the watcher
const watcher = new AutoCommitWatcher();
watcher.start();
// Create restore point on startup
setTimeout(() => {
watcher.createRestorePoint('Session start');
}, 5000);
// Create periodic restore points (every 30 minutes)
setInterval(() => {
watcher.createRestorePoint('Periodic backup');
}, 30 * 60 * 1000);
console.log('🚀 Auto-commit system ready! Press Ctrl+C to stop.');
console.log('📋 Commands available:');
console.log(' ./auto-commit.sh commit [message]');
console.log(' ./auto-commit.sh restore-point [description]');
console.log(' ./auto-commit.sh list');
console.log(' ./auto-commit.sh cleanup');