npm package: @omrijukin/swep
Description: CLI tool to permanently remove files/patterns from Git history
Latest version: 1.0.0

# swep

A powerful CLI tool to permanently remove files or patterns from Git history, including full history rewrite support.

## ⚠️ Warning

**This tool rewrites Git history.** This operation:
- Cannot be undone without a backup
- Will break forks and pull requests
- Requires coordination with your team
- May cause data loss if used incorrectly

**Always use `--dry-run` first and create backups before applying changes.**

## Installation

### Global Installation (Recommended)

```bash
pnpm add -g swep
```

### One-off Usage

```bash
pnpm dlx swep@latest
# or
npx swep
```

### Per-Project Installation

```bash
pnpm add -D swep
```

Then add to your `package.json` scripts:
```json
{
  "scripts": {
    "sanitize": "swep sanitize"
  }
}
```

## Quick Start

### 1. Discover Repositories

```bash
# Scan for Git repositories
swep scan ~/projects --max-depth 5

# Open interactive TUI to select and sanitize
swep scan ~/projects --open-tui
```

### 2. Sanitize a Repository

```bash
# Dry-run (safe, no changes)
swep sanitize . --patterns ".env" --patterns "secrets/**"

# Apply changes (destructive!)
swep sanitize . --patterns ".env*" --apply --backup-name "pre-cleanup"
```

### 3. Interactive Mode

```bash
# Start without arguments to choose repository interactively
swep sanitize

# Or force the prompt
swep sanitize --ask-repo
```

## Commands

### `sanitize`

Remove files/patterns from Git history.

```bash
swep sanitize [path|git-url] [options]
```

**Arguments:**
- `path|git-url` (optional): Local repository path or remote Git URL. If omitted, you'll be prompted to choose.

**Options:**
- `--dry-run` (default): Perform a dry-run without making changes
- `--apply`: Apply the rewrite (required to make actual changes)
- `--force`: Skip confirmations
- `--patterns <patterns...>`: Glob patterns to match files (repeatable)
- `--regex <regexes...>`: Regex patterns to match files (repeatable)
- `--exclude-paths-file <file>`: Load patterns from file (one per line)
- `--backup-name <name>`: Name for backup branch/tag
- `--method <method>`: Rewrite method (`filter-repo`, `bfg`, or `auto`)
- `--keep-commits`: Keep empty commits
- `--prune-empty-commits`: Prune empty commits
- `--no-tags`: Do not rewrite tags
- `--rewrite-tags`: Rewrite tags
- `--remote <name>`: Remote name for push (default: `origin`)
- `--push`: Force push after rewrite (requires `--apply` and `--confirm-push`)
- `--confirm-push`: Confirm force push
- `--temp-dir <path>`: Temporary directory for cloning remote repos
- `--report <format>`: Export report (`json` or `md`)
- `--verbose`: Verbose output
- `--silent`: Silent mode
- `--ask-repo`: Always prompt for repository source
- `--scan-secrets`: Scan for secrets with gitleaks (if installed)
- `--no-color`: Disable colored output
- `--telemetry`: Enable telemetry (opt-in)

### `scan`

Discover local Git repositories.

```bash
swep scan [root] [options]
```

**Arguments:**
- `root` (optional): Root directory to scan (default: current directory)

**Options:**
- `--max-depth <n>`: Maximum depth to scan (default: 5)
- `--include-bare`: Include bare repositories
- `--include-worktrees`: Include worktrees
- `--ignore <globs...>`: Ignore patterns (repeatable)
- `--format <format>`: Output format (`table`, `json`, or `ndjson`)
- `--open-tui`: Open interactive TUI to select repositories
- `--no-cache`: Disable caching
- `--system-root`: Allow scanning system root
- `--verbose`: Verbose output
- `--silent`: Silent mode
- `--no-color`: Disable colored output

## Examples

### Basic Usage

```bash
# Dry-run: see what would be removed
swep sanitize . --patterns ".env" --patterns "secrets/**"

# Apply changes with backup
swep sanitize . \
  --patterns ".env*" \
  --patterns "secrets/**" \
  --apply \
  --backup-name "pre-sanitization-$(date +%Y%m%d)"
```

### Remote Repository

```bash
# Clone and sanitize a remote repository
swep sanitize https://github.com/user/project.git \
  --patterns "**/*.pem" \
  --apply
```

### Using Pattern File

Create `exclude-patterns.txt`:
```
.env*
secrets/**
*.pem
config.ini
```

```bash
swep sanitize . --exclude-paths-file exclude-patterns.txt --dry-run
```

### Scan and Select

```bash
# Discover repositories and select interactively
swep scan ~/projects --max-depth 5 --open-tui
```

### With Secrets Scanning

```bash
# Scan for secrets first, then sanitize
swep sanitize . \
  --scan-secrets \
  --patterns ".env*" \
  --dry-run
```

### Force Push (Dangerous!)

```bash
swep sanitize . \
  --patterns "**/*.pem" \
  --apply \
  --push \
  --confirm-push \
  --remote origin
```

## Backup and Recovery

### Automatic Backups

swep **always** creates a backup before rewriting history, even in dry-run mode. Backups are created as branches or tags with the format:
- `swep-backup/<timestamp>` (default)
- Or your custom name via `--backup-name`

### Restore from Backup

```bash
# Check available backups
git branch -a | grep swep-backup
git tag | grep swep-backup

# Restore from backup branch
git checkout swep-backup/2024-01-15T10-30-00-000Z

# Or restore from backup tag
git checkout swep-backup/2024-01-15T10-30-00-000Z
```

### Manual Recovery

If something goes wrong:

1. **From backup branch/tag:**
   ```bash
   git checkout swep-backup/<name>
   git branch -f main swep-backup/<name>
   ```

2. **From reflog (if available):**
   ```bash
   git reflog
   git reset --hard HEAD@{n}  # n is the reflog entry number
   ```

## Team Coordination

After rewriting history:

1. **Notify your team** immediately
2. **Everyone must re-clone** the repository:
   ```bash
   git fetch origin
   git reset --hard origin/main
   ```
3. **Update forks** - they will need to be recreated or rebased
4. **Update CI/CD** - pipelines may need to be reconfigured
5. **Update documentation** - any references to old commit SHAs will break

## Git LFS

If your repository uses Git LFS, swep will:
- Detect LFS files matching your patterns
- Purge them from LFS storage
- Clean up LFS references

LFS files are handled automatically during the rewrite process.

## Version Locking

You can lock swep to a specific version using `.swep.lock`:

```json
{
  "engineVersion": "1.0.0"
}
```

If the running version doesn't match, swep will warn you and suggest the correct command.

## Exit Codes

- `0`: Success
- `2`: Invalid arguments or patterns
- `>2`: Runtime errors

## Requirements

- **Node.js**: >= 18.0.0
- **Git**: Any recent version
- **git-filter-repo** (preferred) or **BFG Repo-Cleaner** (fallback)

### Installing git-filter-repo

```bash
# macOS
brew install git-filter-repo

# Linux
pip install git-filter-repo

# Or via pipx
pipx install git-filter-repo
```

### Installing BFG (Alternative)

```bash
# macOS
brew install bfg

# Or download from: https://rtyley.github.io/bfg-repo-cleaner/
```

## Safety Features

1. **Dry-run by default** - Never rewrites without `--apply`
2. **Automatic backups** - Always creates backup before changes
3. **Double confirmation** - `--push` requires both `--apply` and `--confirm-push`
4. **Integrity validation** - Runs `git fsck` after rewrite
5. **System root protection** - Prevents accidental system-wide scans

## Limitations

- Rewriting history breaks forks and pull requests
- Large repositories (>2GB) may take significant time
- Some Git hosting services may have restrictions
- LFS cleanup requires LFS to be properly configured

## Troubleshooting

### "git-filter-repo not found"

Install git-filter-repo or use `--method bfg` to use BFG instead.

### "Repository integrity check failed"

This usually means the rewrite corrupted the repository. Restore from backup immediately.

### "No files matched"

Check your patterns. Use `--verbose` to see what's being scanned.

### Large Repository Performance

For very large repositories:
- Use `--method filter-repo` (faster than BFG)
- Consider running during off-hours
- Monitor disk space

## Contributing

Contributions welcome! Please read the contributing guidelines first.

## License

MIT

## Support

For issues and questions:
- GitHub Issues: [link]
- Documentation: [link]

---

**Remember**: Always test with `--dry-run` first, and coordinate with your team before rewriting shared repository history!