Version: 2.0 (with Non-Interactive Support)
Last Updated: January 23, 2025
Related Code Files:
safegit.py- Main wrapper with interception logic (1226 lines)safe_git_commands.py- Core safety analysis engine (830 lines)safegit_undo_stack.py- Multi-level undo system with atomic metadata capturetest_safegit_*.py- Comprehensive test suites
SafeGIT is an enterprise-grade protective wrapper around git that prevents accidental data loss from dangerous operations. Originally designed to prevent AI agent disasters (like the Replit incident), it now supports both interactive safety education and fully automated workflows for CI/CD pipelines.
SafeGIT operates on three principles:
- Prevention is better than recovery - Intercept dangerous commands before execution
- Education over restriction - Teach users safer alternatives
- Zero friction for safe operations - Only intervene for dangerous commands
- 37+ Dangerous Pattern Detection: Comprehensive coverage of all common git disasters
- Automatic Backups: Creates stashes/backups before destructive operations
- Smart Conversions: Converts dangerous commands to safer alternatives
- Multi-Level Undo System: Complete operation history with recovery paths
- Branch Protection Detection: Platform-specific protection rules (GitHub, GitLab, Bitbucket)
- Atomic File Operations: Thread-safe with cross-platform file locking
- Risk Assessment: Graduated confirmations based on operation danger level
- Recovery Hints: Shows reflog commands after potentially dangerous operations
- Impact Analysis: Explains what each command will do before execution
- Alternative Suggestions: Recommends safer approaches
- Dry-Run Mode: Preview command effects without execution
- Non-Interactive Mode: Full CI/CD and script support
- Graduated Safety Levels: Different flags for different risk levels
- Environment Variables: Comprehensive configuration options
- CI Platform Auto-Detection: Works seamlessly in automated environments
- Automation Logging: Complete audit trail of automated operations
chmod +x safegit.py
sudo ln -s $(pwd)/safegit.py /usr/local/bin/safegit
# Verify installation
safegit --versionalias git='python3 /path/to/safegit.py'
echo "alias git='python3 /path/to/safegit.py'" >> ~/.bashrcchmod +x safegit.py
sudo cp safegit.py /usr/local/bin/safegitSafeGIT supports multiple configuration methods with a clear priority hierarchy.
SafeGIT integrates with the Code Intelligence Toolkit's unified configuration system. Create a .pytoolsrc file in your project root:
[safegit]
# Non-interactive mode settings
non_interactive = false # Set to true for CI/CD environments
assume_yes = false # Auto-confirm safe operations
force_yes = false # DANGEROUS: Auto-confirm ALL operations
dry_run = false # Preview mode - show what would happen
# You can also use the [defaults] section for common settings
[defaults]
# These apply to SafeGIT if [safegit] section is not present
dry_run = false
assume_yes = false-
Command-line flags (highest priority)
--yes,--force-yes,--dry-run,--non-interactive
-
Environment variables
SAFEGIT_NONINTERACTIVE,SAFEGIT_ASSUME_YES,SAFEGIT_FORCE_YES
-
Configuration file (.pytoolsrc)
[safegit]section settings[defaults]section (fallback)
-
Built-in defaults (lowest priority)
- All features disabled by default
[safegit]
non_interactive = false
assume_yes = false
dry_run = false[safegit]
non_interactive = true
assume_yes = true
force_yes = false # Still require explicit --force for dangerous ops
dry_run = false[safegit]
non_interactive = true
assume_yes = true
force_yes = false
dry_run = true # Preview all operationsSafeGIT provides graduated protection based on operation risk:
safegit status
safegit log
safegit diff
safegit add file.txt
safegit commit -m "message"
safegit pull
safegit fetchsafegit checkout main # Warns about uncommitted changes
safegit merge feature # Checks for conflicts
safegit rebase main # History rewrite warningsafegit reset --hard # Creates stash, requires "PROCEED"
safegit clean -fdx # Creates zip backup, requires "DELETE"
safegit push --force # Converts to --force-with-lease, requires risk acceptancePerfect for CI/CD pipelines and automated scripts:
# Auto-confirm safe operations
safegit --yes add .
safegit --yes commit -m "Automated commit"
safegit --yes pull
# Force dangerous operations (use with extreme caution!)
safegit --force-yes reset --hard HEAD~1
safegit --force-yes clean -fdx
# Strict non-interactive mode (fails on any prompt)
safegit --non-interactive --yes status
safegit --batch --force-yes push# Create or edit .pytoolsrc in your project root
[safegit]
non_interactive = false # Set to true for automation
assume_yes = false # Set to true to auto-confirm safe operations
force_yes = false # DANGEROUS: Set to true only in fully automated environments
dry_run = false # Set to true to preview commands without executing# Enable non-interactive mode
export SAFEGIT_NONINTERACTIVE=1
# Auto-confirm safe operations
export SAFEGIT_ASSUME_YES=1
# Force all confirmations (dangerous!)
export SAFEGIT_FORCE_YES=1
# CI environments are auto-detected
# Supported: CI, GITHUB_ACTIONS, GITLAB_CI, JENKINS_URL, TRAVISPriority Order: Environment variables > .pytoolsrc config > Built-in defaults
-
Low Risk (works with
--yesorSAFEGIT_ASSUME_YES):- add, commit, pull, fetch, status, log, diff
- checkout -b (new branch)
- stash, tag, merge (fast-forward)
-
Medium Risk (requires
--yeswith warnings):- checkout (existing branch)
- merge (non-fast-forward)
- rebase (interactive)
- cherry-pick
-
High Risk (requires
--force-yesorSAFEGIT_FORCE_YES):- reset --hard
- clean -fdx
- push --force / push --mirror
- branch -D
- stash clear
- gc --prune=now
- reflog expire
- update-ref -d
Preview any command's effects without execution:
safegit --dry-run reset --hard HEAD~3
# Output: Would reset to 3 commits ago, losing changes in: file1.js, file2.py
safegit --dry-run clean -fdx
# Output: Would delete 15 untracked files (total size: 2.3MB)
safegit --dry-run push --force origin main
# Output: Would force push, overwriting 5 remote commitsSafeGIT maintains a complete operation history with recovery paths:
# Undo last operation
safegit undo
# Interactive undo (select from history)
safegit undo --interactive
# View operation history
safegit undo-history
# Export complete history
safegit export-historyEach undo entry includes:
- Original command and parameters
- Repository state at time of operation
- Automatic backups (if created)
- Recovery script with exact commands
- Recovery hints and best practices
SafeGIT adapts its behavior based on environment and workflow:
safegit set-env production # Maximum restrictions
safegit set-env staging # Moderate restrictions
safegit set-env development # Default restrictionsEnvironment-Specific Restrictions:
- development (default): Standard SafeGIT protections apply
- staging: Standard protections, similar to development
- production: Maximum safety restrictions
- No force pushes (
push --force,push -f) - No hard resets (
reset --hard) - No force cleans (
clean -fdx,clean -fxd) - No rebasing operations
- No force pushes (
safegit set-mode normal # Default behavior
safegit set-mode code-freeze # Only critical fixes allowed
safegit set-mode maintenance # Reserved for future use
safegit set-mode paranoid # Allowlist approach (only safe commands)Mode-Specific Restrictions:
- normal (default): Standard SafeGIT behavior with all safety features
- code-freeze: Restricts write operations except for hotfix branches
- Blocks: push, commit, merge, rebase, reset, clean
- Exception: Commands containing "hotfix" or "HOTFIX" are allowed
- Perfect for release periods when only critical fixes should be merged
- maintenance: Currently same as normal mode (reserved for future features)
- paranoid: Allowlist approach - only explicitly safe commands are permitted
- Allowed base commands: status, log, diff, fetch, show, ls-files, branch, tag, remote
- Additional restrictions on allowed commands:
branch: No deletion flags (-d, -D, --delete)tag: Only listing allowed (-l, --list, -n)remote: Only show/get-url/-v allowed
safegit show-context
# Output: Environment: production, Mode: code-freeze
# JSON output for scripting
safegit show-context --json
# Output: {"environment": "production", "mode": "code-freeze", "restrictions": [], ...}# Add custom pattern-based restrictions
safegit add-restriction "experimental" # Blocks any command containing "experimental"
safegit add-restriction "force" # Blocks any command containing "force"
# Remove restrictions
safegit remove-restriction "experimental"
# View all restrictions in current context
safegit show-contextAll context settings are stored in .git/safegit-context.json and persist across sessions. The file includes:
- Current environment and mode
- Custom restrictions list
- Creation and last update timestamps
# Production deployment scenario
safegit set-env production
safegit set-mode code-freeze
# Now only hotfix branches can be pushed, no force operations allowed
# Development with experimental features
safegit set-env development
safegit add-restriction "experimental"
# Prevents accidental commits to experimental branches
# Maximum safety for junior developers
safegit set-mode paranoid
# Only read operations allowed, perfect for code review sessionsAI agents executing git commands can cause catastrophic data loss, as seen in the Replit incident where an AI deleted an entire production database.
SafeGIT provides comprehensive protection through a single rule:
# For any AI system - just replace 'git' with 'safegit'
command = command.replace('git ', 'safegit ')For AI agents, the safest approach is to configure SafeGIT via .pytoolsrc:
# .pytoolsrc for AI agents
[safegit]
non_interactive = true # No prompts in AI context
assume_yes = true # Auto-confirm safe operations
force_yes = false # Never auto-confirm dangerous operations
dry_run = false # Set to true for testingThis ensures consistent behavior without relying on environment variables that might be forgotten.
@tool
def run_git_command(command: str, auto_confirm: bool = False) -> str:
"""Run a git command safely using safegit wrapper."""
if command.startswith('git '):
raise ValueError("Direct git commands are forbidden. Use 'safegit' instead.")
if not command.startswith('safegit '):
command = f'safegit {command}'
# Optional: Override config with environment variables
env = os.environ.copy()
if auto_confirm:
env['SAFEGIT_NONINTERACTIVE'] = '1'
env['SAFEGIT_ASSUME_YES'] = '1'
result = subprocess.run(command, shell=True, capture_output=True, text=True, env=env)
return result.stdout + result.stderrSafeGIT only works if direct git access is blocked! You MUST configure your AI agents to prevent direct git command execution.
-
System Prompt / Instructions
You are FORBIDDEN from using 'git' commands directly. ALWAYS use 'safegit' or './run_any_python_tool.sh safegit.py' instead. Direct git commands like 'git reset --hard' are strictly prohibited.
-
Function-Level Blocking
BLOCKED_COMMANDS = ['git', 'rm', 'mv', 'cp', 'dd', 'shred'] def execute_command(cmd: str): base_cmd = cmd.split()[0] if base_cmd in BLOCKED_COMMANDS: raise ValueError(f"Direct '{base_cmd}' is forbidden. Use safe wrappers.")
-
Command Replacement
# Automatically replace git with safegit if cmd.startswith('git '): cmd = cmd.replace('git ', 'safegit ', 1)
- AI doesn't understand danger - It will happily run
git reset --hardif allowed - One command can destroy everything - No undo for direct git operations
- SafeGIT can be bypassed - If direct git access exists, protection is useless
- Defense requires blocking - You must block at the source
# These should ALL be rejected by your AI:
test_commands=(
"git reset --hard HEAD~10"
"git clean -fdx"
"git push --force origin main"
"rm -rf important_directory"
)
# If ANY of these execute, your AI setup is unsafe!See AI_SAFETY_SETUP.md for complete configuration instructions.
name: Deploy
on: push
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install SafeGIT
run: |
chmod +x safegit.py
sudo ln -s $(pwd)/safegit.py /usr/local/bin/safegit
- name: Safe Deploy
env:
SAFEGIT_ASSUME_YES: 1
run: |
safegit add .
safegit commit -m "Deploy: ${{ github.sha }}"
safegit pushdeploy:
script:
- export SAFEGIT_ASSUME_YES=1
- safegit add .
- safegit commit -m "Deploy: $CI_COMMIT_SHA"
- safegit pushSafeGIT protects against 37+ dangerous operations, including:
reset --hard- Creates automatic stash before resetclean -fdx- Creates zip backup of all files to be deletedcheckout --force- Stashes changes before force checkoutswitch --discard-changes- Protects uncommitted work
rebase- Warns about history changes, shows recoverycommit --amend- Checks if commit was already pushedfilter-branch- Extreme warnings about repository corruption
push --force- Converts to--force-with-lease, checks branch protectionpush --mirror- Requires "MIRROR PUSH" confirmationpush --delete- Remote branch deletion protection
branch -D- Local branch deletion warningsupdate-ref -d- Low-level reference deletion protectionreflog expire- Safety net removal warnings
gc --prune=now- Immediate garbage collection warningsgc --aggressive- Performance impact warningsstash clear- Creates text backup before clearing
SafeGIT maintains comprehensive logs for all operations:
{
"timestamp": "2025-01-23T10:30:00",
"command": "reset --hard HEAD~1",
"action": "intercepted",
"mode": "non-interactive",
"flags": {
"force_yes": true,
"dry_run": false
},
"ci_detected": true,
"backup_created": {
"type": "stash",
"ref": "stash@{0}",
"message": "SAFEGIT: Auto-backup before reset --hard"
}
}Log locations:
.git/safegit-log.json- All operations.git/safegit-undo-stack.json- Undo history.git/safegit-context.json- Environment settings
- Overhead: ~50ms per command (negligible)
- Backup Creation: <1 second for most operations
- Pattern Matching: Compiled regex for efficiency
- Atomic Operations: Thread-safe with minimal locking
# Verify you're using safegit, not git
which git
which safegit
# Check if alias is set
alias | grep gitchmod +x safegit.py
chmod +x safe_git_commands.py
chmod +x safegit_undo_stack.py# Check configuration file
cat .pytoolsrc | grep -A 5 "\[safegit\]"
# Check environment variables (these override config)
env | grep SAFEGIT
# Enable debug output
export SAFEGIT_DEBUG=1
# Test configuration loading
python3 -c "from common_config import load_config, get_config_value; \
config = load_config(); \
print('non_interactive:', get_config_value('safegit', 'non_interactive', False, config)); \
print('assume_yes:', get_config_value('safegit', 'assume_yes', False, config))"# Ensure Python 3.6+ is installed
python3 --version
# Check all files are in same directory
ls safe_git_commands.py safegit_undo_stack.py-
safegit.py (1226 lines)
- Main entry point and command interceptor
- Pattern matching engine
- Handler dispatch system
- Non-interactive mode logic
-
safe_git_commands.py (830 lines)
- Core safety analysis
- Backup creation logic
- State verification
- Recovery hint generation
-
safegit_undo_stack.py
- Atomic undo journal
- Operation metadata capture
- Recovery script generation
- Cross-platform file locking
- Fail-Safe: Always err on the side of caution
- Atomic Operations: All-or-nothing file operations
- Educational: Teach users safer git practices
- Zero Data Loss: Multiple backup mechanisms
- Cross-Platform: Works on Windows, macOS, Linux
- ✅ Use SafeGIT as your default git interface
- ✅ Pay attention to warnings and suggestions
- ✅ Use dry-run mode when unsure
- ✅ Learn from recovery hints
- ✅ Review operation history regularly
- ✅ Use
--yesfor safe automation - ✅ Test with
--dry-runin staging - ✅ Set appropriate environment variables
- ✅ Monitor logs for blocked operations
- ✅ Use graduated safety levels appropriately
- ✅ Always use 'safegit' instead of 'git'
- ✅ Configure non-interactive mode
- ✅ Handle blocked operations gracefully
- ✅ Log all git operations
- ✅ Never use
--force-yeswithout human approval
Planned features for future versions:
- Remote repository state caching
- Team-wide safety policies
- Integration with git hooks
- Machine learning for risk assessment
- Visual operation history browser
SafeGIT is part of the code-intelligence-toolkit project. Contributions welcome!
- Test thoroughly with all test suites
- Update documentation
- Follow existing patterns
- Add tests for new features
- Consider backward compatibility
Part of the code-intelligence-toolkit project.
Remember: SafeGIT is your safety net, not a replacement for understanding git. Use it to learn safer git practices and prevent disasters before they happen!