Skip to content

How Do I Set Up a Safe Git Workflow for AI Coding Assistants to Prevent Code Loss?

I lost three hours of work yesterday.

My AI coding assistant decided to run git checkout . on my main branch while I had uncommitted changes. Just like that, my work vanished. No warning. No confirmation. No mercy.

If you’re using AI coding assistants like Claude Code, OpenCode CLI, or GitHub Copilot, you’re probably one wrong instruction away from the same disaster. These tools are powerful but they don’t understand the value of your uncommitted work.

Let me show you how I built a defense system that prevents this from ever happening again.

The Problem: AI Assistants Don’t Respect Your Workflow

AI coding assistants operate with good intentions but dangerous assumptions:

  • They assume you want clean, working directories
  • They’re happy to run destructive git commands without asking
  • They’ll commit directly to your main branch
  • They don’t naturally create feature branches
  • They skip running tests before committing

I learned this the hard way. After my first disaster, I added more rules. After my second near-miss, I realized I needed a systematic approach.

The Solution: Three Layers of Protection

I built my defense in three layers:

  1. Global AGENTS.md - Rules that the AI assistant reads before every task
  2. Git Aliases - Safe workflow shortcuts I can invoke
  3. Shell Scripts - Automated checks and safeguards

Let me walk you through each layer.

Layer 1: The AGENTS.md Configuration File

The most effective protection I found was creating a global AGENTS.md file. This file lives in my home directory and gets loaded by the AI assistant before every session.

Here’s the exact configuration I use:

AGENTS.md - Git Workflow Rules
# Git Workflow Rules (MANDATORY)
Before starting ANY coding task:
1. Check if current branch has uncommitted changes
2. If yes, COMMIT or STASH before continuing
3. Create a new feature branch before editing: `git checkout -b agent/<short-task-name>`
4. NEVER commit directly to main or master
## Commit Message Format
- Use conventional commits: feat:, fix:, refactor:, docs:, test:, chore:
- Write clear, descriptive messages
- Keep commits atomic and focused
## Before Committing
- Run tests if they exist
- Run linters if configured
- Ensure the project builds
- Verify no secrets in code
## Branch Naming
- Use format: agent/<short-task-name>
- Examples: agent/add-auth, agent/fix-login, agent/refactor-cache
## Forbidden Actions
- NO `git checkout .` without explicit user confirmation
- NO `git reset --hard` without explicit user confirmation
- NO `git push --force` to main/master
- NO skipping hooks with --no-verify
## Session Export
- Use `opencode export` to save session history
- Keep records for debugging and traceability

This file creates a contract between you and your AI assistant. The assistant reads these rules before starting any task.

How to Set Up Global AGENTS.md

Place this file in your home directory:

Installing AGENTS.md globally
# Create the global AGENTS.md file
cat > ~/.claude/AGENTS.md << 'EOF'
# Git Workflow Rules (MANDATORY)
Before starting ANY coding task:
1. Check if current branch has uncommitted changes
2. If yes, COMMIT or STASH before continuing
3. Create a new feature branch before editing: git checkout -b agent/<short-task-name>
4. NEVER commit directly to main or master
EOF
# Verify the file was created
cat ~/.claude/AGENTS.md

For Claude Code, this file is automatically loaded. For other assistants, you may need to reference it in your project’s .cursorrules or similar configuration.

Layer 2: Git Aliases for Safe Workflows

I created git aliases that enforce safe patterns. These aliases act as guardrails:

Git aliases for safe AI workflows
# Add these to your ~/.gitconfig
# Safe start: creates feature branch with safeguards
git config --global alias.safe-start '!f() {
# Check for uncommitted changes
if ! git diff-index --quiet HEAD --; then
echo "ERROR: You have uncommitted changes. Commit or stash first."
exit 1
fi
# Check if on main/master
branch=$(git rev-parse --abbrev-ref HEAD)
if [ "$branch" = "main" ] || [ "$branch" = "master" ]; then
if [ -z "$1" ]; then
echo "ERROR: Please provide a branch name: git safe-start <branch-name>"
exit 1
fi
git checkout -b "agent/$1"
echo "Created and switched to agent/$1"
else
echo "Already on branch: $branch"
fi
}; f'
# Safe commit: runs tests before committing
git config --global alias.safe-commit '!f() {
# Run tests if package.json exists
if [ -f "package.json" ]; then
echo "Running tests..."
npm test
if [ $? -ne 0 ]; then
echo "ERROR: Tests failed. Fix before committing."
exit 1
fi
fi
# Commit with message
if [ -z "$1" ]; then
echo "ERROR: Please provide a commit message."
exit 1
fi
git commit -m "$1"
}; f'
# Check status before destructive operations
git config --global alias.safe-checkout '!f() {
if ! git diff-index --quiet HEAD --; then
echo "WARNING: You have uncommitted changes!"
echo "Files modified:"
git status --short
echo ""
echo "Use 'git stash' to save changes or 'git commit' to keep them."
read -p "Continue with checkout? (y/N): " confirm
if [ "$confirm" != "y" ] && [ "$confirm" != "Y" ]; then
exit 1
fi
fi
git checkout "$@"
}; f'
# Show current workflow status
git config --global alias.workflow-status '!f() {
echo "=== Current Branch ==="
git branch --show-current
echo ""
echo "=== Uncommitted Changes ==="
if git diff-index --quiet HEAD --; then
echo "No uncommitted changes"
else
git status --short
fi
echo ""
echo "=== Recent Commits ==="
git log --oneline -5
}; f'

Now instead of running git checkout . (dangerous), I tell my AI assistant: “Run git workflow-status first, then use safe-start to create a branch.”

Using the Aliases

Here’s my typical workflow with an AI assistant:

Example safe workflow session
# 1. Check current state
git workflow-status
# 2. Start new work safely
git safe-start add-user-auth
# 3. Make changes with AI assistant...
# (AI makes file edits)
# 4. Commit safely with tests
git safe-commit "feat: add user authentication"
# 5. Push to remote
git push -u origin agent/add-user-auth

Layer 3: Shell Script for Complete Safety

For maximum protection, I wrapped everything into a single script:

ai-safe-workflow.sh - Complete protection script
#!/bin/bash
# AI-Safe Git Workflow Script
# Prevents AI coding assistants from destroying work
set -e
COMMAND=${1:-"status"}
BRANCH_NAME=${2:-""}
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
log_info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
check_uncommitted() {
if ! git diff-index --quiet HEAD --; then
return 0 # Has uncommitted changes
fi
return 1 # Clean
}
get_current_branch() {
git rev-parse --abbrev-ref HEAD
}
is_protected_branch() {
local branch=$(get_current_branch)
[ "$branch" = "main" ] || [ "$branch" = "master" ]
}
cmd_status() {
log_info "Current branch: $(get_current_branch)"
echo ""
if check_uncommitted; then
log_warn "You have uncommitted changes:"
git status --short
echo ""
log_warn "Run 'commit' or 'stash' before starting new work."
else
log_info "Working directory is clean"
fi
echo ""
log_info "Recent commits:"
git log --oneline -5
}
cmd_start() {
if [ -z "$BRANCH_NAME" ]; then
log_error "Please provide a branch name: ./ai-safe-workflow.sh start <branch-name>"
exit 1
fi
if check_uncommitted; then
log_error "You have uncommitted changes!"
echo ""
git status --short
echo ""
log_error "Commit or stash before starting new work."
exit 1
fi
if is_protected_branch; then
git checkout -b "agent/$BRANCH_NAME"
log_info "Created and switched to agent/$BRANCH_NAME"
else
log_warn "Already on branch: $(get_current_branch)"
read -p "Create new branch anyway? (y/N): " confirm
if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then
git checkout -b "agent/$BRANCH_NAME"
fi
fi
}
cmd_commit() {
local message="$BRANCH_NAME"
if [ -z "$message" ]; then
log_error "Please provide a commit message: ./ai-safe-workflow.sh commit \"your message\""
exit 1
fi
# Check for tests
if [ -f "package.json" ] && grep -q '"test"' package.json; then
log_info "Running tests..."
if npm test; then
log_info "Tests passed"
else
log_error "Tests failed. Fix before committing."
exit 1
fi
fi
# Check for linter
if [ -f "package.json" ] && grep -q '"lint"' package.json; then
log_info "Running linter..."
if npm run lint; then
log_info "Linting passed"
else
log_warn "Linting issues found. Review before committing."
read -p "Continue with commit? (y/N): " confirm
if [ "$confirm" != "y" ] && [ "$confirm" != "Y" ]; then
exit 1
fi
fi
fi
git commit -m "$message"
log_info "Committed: $message"
}
cmd_stash() {
if check_uncommitted; then
git stash push -m "ai-safe-backup-$(date +%Y%m%d-%H%M%S)"
log_info "Stashed uncommitted changes"
else
log_info "Nothing to stash"
fi
}
cmd_unstash() {
git stash pop
log_info "Restored stashed changes"
}
cmd_export-session() {
if command -v opencode &> /dev/null; then
opencode export
log_info "Session exported"
else
log_warn "opencode CLI not found. Install it for session export."
fi
}
# Main command router
case $COMMAND in
status)
cmd_status
;;
start)
cmd_start
;;
commit)
cmd_commit
;;
stash)
cmd_stash
;;
unstash)
cmd_unstash
;;
export)
cmd_export-session
;;
*)
echo "Usage: $0 {status|start|commit|stash|unstash|export}"
echo ""
echo "Commands:"
echo " status - Show current workflow status"
echo " start - Create new feature branch safely"
echo " commit - Commit with tests and lint checks"
echo " stash - Stash uncommitted changes"
echo " unstash - Restore stashed changes"
echo " export - Export session history (requires opencode)"
exit 1
;;
esac

Make it executable and available:

Installing the safety script
chmod +x ai-safe-workflow.sh
sudo mv ai-safe-workflow.sh /usr/local/bin/ai-safe
# Now you can use it anywhere
ai-safe status
ai-safe start fix-login-bug
ai-safe commit "fix: resolve login redirect issue"

Why This Matters

After implementing this workflow, I’ve had zero code loss incidents. Here’s why each layer matters:

AGENTS.md catches problems before they happen. The AI reads the rules and adjusts its behavior. It’s like having a senior developer watching over the AI’s shoulder.

Git aliases create muscle memory. Even when I’m working without AI, I use git safe-start because it’s safer than raw git commands.

Shell scripts provide a single source of truth. When I’m stressed or rushing, I don’t have to remember the safe sequence. I just run ai-safe status and follow the prompts.

Common Mistakes to Avoid

I’ve made these mistakes so you don’t have to:

Mistake 1: Relying on Single-Layer Protection

At first, I only used the AGENTS.md file. But sometimes the AI assistant would skip reading it, or I’d forget to reference it. The triple-layer approach gives you defense in depth.

Mistake 2: Not Running Tests Before Committing

I once had an AI assistant commit code that broke the build. The tests existed but weren’t run. Now my safe-commit alias always runs tests.

Mistake 3: Working Directly on Main Branch

This is how my first disaster happened. I was making “small fixes” directly on main. The AI ran git checkout . and my changes were gone. Now I always use feature branches, even for tiny changes.

Mistake 4: Not Stashing Before Destructive Operations

Sometimes you need to switch contexts quickly. I used to just checkout another branch, losing uncommitted work. Now I always stash first with ai-safe stash.

Mistake 5: Skipping Conventional Commits

Without conventional commit format, my git history was a mess. AI assistants would write vague messages like “updated code.” The AGENTS.md rules enforce better messages.

How I Use This Daily

Here’s my typical workflow when starting a new task with an AI assistant:

  1. Check status: ai-safe status
  2. Start clean: If dirty, ai-safe stash or commit first
  3. Create branch: ai-safe start my-feature
  4. Work with AI: Let the assistant make changes
  5. Review: Check what files changed
  6. Commit safely: ai-safe commit "feat: my feature"
  7. Push: git push -u origin agent/my-feature
  8. Create PR: Use GitHub CLI or web interface

This workflow has become second nature. The AI assistant respects it, I respect it, and my code stays safe.

Branch Protection Rules: Beyond local safeguards, enable branch protection on your remote repository. This prevents force pushes to main/master even if someone (or some AI) tries to bypass local rules.

Git Hooks: Consider using pre-commit hooks for additional safety. Tools like Husky can run linting, formatting, and tests automatically before each commit.

Session Export: If you’re using OpenCode CLI, the opencode export command saves your session history. This is invaluable for debugging what went wrong and for compliance purposes.

Conventional Commits: The feat/fix/refactor prefix system enables automatic changelog generation. Tools like standard-version can create release notes from your commit history.

Final Thoughts

AI coding assistants are transformative productivity tools, but they need guardrails. The three-layer protection system I’ve shown you prevents the most common disasters:

  • Global AGENTS.md sets the rules
  • Git aliases create safe shortcuts
  • Shell scripts enforce the workflow

Start with the AGENTS.md file. It’s the highest-impact, lowest-effort improvement you can make today. Add the aliases and scripts as you get comfortable with the workflow.

Your future self will thank you when you realize you just prevented a catastrophic code loss. Trust me.

Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments