Repository Cleanup Before Master-to-Main Migration

This guide helps you clean up and consolidate Git repositories before migrating from master to main branch. Use this to audit all your repositories and ensure a clean migration.

Overview

Before migrating from master to main, you should:

  1. Audit all branches - Identify what needs to be kept vs. deleted

  2. Merge important work - Consolidate valuable changes

  3. Clean up obsolete branches - Remove outdated development branches

  4. Verify repository state - Ensure everything important is preserved

Quick Assessment Commands

1. Check All Branches

# See all local and remote branches
git branch -a

# See branch relationships graphically
git log --oneline --graph --decorate --all

# Compare branches
git log --oneline --left-right master...branch-name

2. Identify Branch Status

# Check what's in other branches that master doesn't have
git log master..branch-name --oneline

# Check what's in master that other branches don't have
git log branch-name..master --oneline

# See divergence between branches
git show-branch master branch-name

3. Check Branch Ages

# See last commit date for each branch
git for-each-ref --format='%(refname:short) %(committerdate)' refs/heads

# See all branches sorted by last commit date
git for-each-ref --sort=-committerdate --format='%(refname:short) %(committerdate:short) %(objectname:short)' refs/heads

Decision Matrix: Keep vs. Delete

✅ KEEP branches that have:

  • Unreleased features: Work not yet merged to master

  • Active development: Recent commits (within last month)

  • Unique commits: Changes that don’t exist in master

  • Future work: Planned features or experiments

❌ DELETE branches that are:

  • Behind master: All commits already in master

  • Old releases: Historical snapshots (like version2)

  • Completed features: Already merged and released

  • Abandoned experiments: No longer relevant

Step-by-Step Cleanup Process

Step 1: Repository Assessment

Create a branch audit for each repository:

#!/bin/bash
# save as: audit-repo.sh

echo "=== REPOSITORY AUDIT ==="
echo "Repository: $(basename $(git rev-parse --show-toplevel))"
echo "Current branch: $(git branch --show-current)"
echo ""

echo "=== ALL BRANCHES ==="
git branch -a
echo ""

echo "=== BRANCH AGES ==="
git for-each-ref --sort=-committerdate --format='%(refname:short) - %(committerdate:short) - %(objectname:short)' refs/heads
echo ""

echo "=== BRANCH ANALYSIS ==="
for branch in $(git branch --format='%(refname:short)' | grep -v '^master$'); do
    echo "Branch: $branch"
    
    # Check if branch is ahead of master
    ahead=$(git rev-list master..$branch --count 2>/dev/null || echo "0")
    behind=$(git rev-list $branch..master --count 2>/dev/null || echo "0")
    
    echo "  - $ahead commits ahead of master"
    echo "  - $behind commits behind master"
    
    if [ "$ahead" -eq 0 ]; then
        echo "  - ❌ CANDIDATE FOR DELETION (no unique commits)"
    elif [ "$behind" -gt 10 ]; then
        echo "  - ⚠️  VERY OUTDATED (consider rebasing or deleting)"
    else
        echo "  - ✅ HAS UNIQUE WORK (keep and consider merging)"
    fi
    echo ""
done

Step 2: Clean Up Process

For Outdated Branches (Behind Master)

# Example: version2 branch that's behind master

# 1. Verify branch is outdated
git log version2..master --oneline  # Should show commits
git log master..version2 --oneline  # Should show nothing

# 2. Delete local branch
git branch -d version2

# 3. Delete remote branch
git push origin --delete version2

# 4. Clean up tracking references
git remote prune origin

For Branches with Unique Work

# Example: feature-branch with unreleased work

# 1. Check what's unique
git log master..feature-branch --oneline

# 2. Merge if ready
git checkout master
git merge feature-branch
git branch -d feature-branch

# 3. Or rebase if you want linear history
git checkout feature-branch
git rebase master
git checkout master
git merge feature-branch  # Fast-forward
git branch -d feature-branch

For Experimental/Abandoned Branches

# Save work first (optional)
git tag archive/experimental-feature experimental-feature

# Then delete
git branch -D experimental-feature  # Force delete
git push origin --delete experimental-feature

Real-World Examples

Example 1: build-cert Repository (Your Case)

Situation:

  • master: Has v2.1.1 + latest work

  • version2: Stopped at v2.0.0 (outdated)

Analysis:

git log master..version2 --oneline   # Nothing (version2 has no unique work)
git log version2..master --oneline   # 7 commits (master is ahead)

Action: Delete version2 (completed above)

git branch -d version2
git push origin --delete version2
git remote prune origin

Example 2: Project with Active Development

Situation:

  • master: Production code

  • feature/new-api: 5 commits ahead, 2 behind

  • experiment/ml-model: 10 commits ahead, 20 behind

  • hotfix/security: 1 commit ahead, 0 behind

Actions:

# Merge ready hotfix
git checkout master
git merge hotfix/security
git branch -d hotfix/security

# Rebase and merge new API
git checkout feature/new-api
git rebase master
git checkout master
git merge feature/new-api
git branch -d feature/new-api

# Archive experimental work (too diverged)
git tag archive/ml-experiment experiment/ml-model
git branch -D experiment/ml-model

Example 3: Multiple Release Branches

Situation:

  • master: Current work

  • release/v1.0: Old release branch

  • release/v2.0: Another old release

  • develop: GitFlow-style development

Actions:

# Keep important release tags
git tag v1.0-final release/v1.0
git tag v2.0-final release/v2.0

# Merge development work
git checkout master
git merge develop

# Clean up old branches
git branch -d release/v1.0
git branch -d release/v2.0
git branch -d develop

Automation Script

Save this as cleanup-before-migration.sh:

#!/bin/bash
set -e

REPO_DIR="${1:-.}"
cd "$REPO_DIR"

echo "🔍 Analyzing repository: $(basename $(pwd))"

# Check if we're in a git repo
if ! git rev-parse --git-dir > /dev/null 2>&1; then
    echo "❌ Not a git repository"
    exit 1
fi

# Check if master branch exists
if ! git show-ref --verify --quiet refs/heads/master; then
    echo "ℹ️  No master branch found - may already be migrated"
    exit 0
fi

echo ""
echo "📊 BRANCH ANALYSIS"
echo "=================="

# List all branches with analysis
for branch in $(git branch --format='%(refname:short)' | grep -v '^master$'); do
    echo ""
    echo "Branch: $branch"
    
    # Get commit counts
    ahead=$(git rev-list master..$branch --count 2>/dev/null || echo "0")
    behind=$(git rev-list $branch..master --count 2>/dev/null || echo "0")
    
    # Get last commit date
    last_commit=$(git log -1 --format='%cr' $branch 2>/dev/null || echo "unknown")
    
    echo "  📊 $ahead ahead, $behind behind master"
    echo "  📅 Last commit: $last_commit"
    
    # Provide recommendation
    if [ "$ahead" -eq 0 ]; then
        echo "  💡 RECOMMENDATION: Delete (no unique commits)"
        echo "      Commands:"
        echo "        git branch -d $branch"
        echo "        git push origin --delete $branch"
    elif [ "$behind" -gt 20 ]; then
        echo "  💡 RECOMMENDATION: Archive or rebase (very outdated)"
        echo "      Commands:"
        echo "        git tag archive/$branch $branch"
        echo "        git branch -D $branch"
    else
        echo "  💡 RECOMMENDATION: Merge or keep (has unique work)"
        echo "      Commands:"
        echo "        git checkout master"
        echo "        git merge $branch"
    fi
done

echo ""
echo "🎯 READY FOR MIGRATION?"
echo "======================="

# Check if any branches need attention
outdated_branches=$(git for-each-ref --format='%(refname:short)' refs/heads | grep -v '^master$' | while read branch; do
    ahead=$(git rev-list master..$branch --count 2>/dev/null || echo "0")
    if [ "$ahead" -eq 0 ]; then
        echo $branch
    fi
done)

active_branches=$(git for-each-ref --format='%(refname:short)' refs/heads | grep -v '^master$' | while read branch; do
    ahead=$(git rev-list master..$branch --count 2>/dev/null || echo "0")
    if [ "$ahead" -gt 0 ]; then
        echo $branch
    fi
done)

if [ -n "$outdated_branches" ]; then
    echo "⚠️  Found outdated branches that can be safely deleted:"
    echo "$outdated_branches" | sed 's/^/    /'
fi

if [ -n "$active_branches" ]; then
    echo "⚠️  Found branches with unique work - review before migration:"
    echo "$active_branches" | sed 's/^/    /'
fi

if [ -z "$outdated_branches" ] && [ -z "$active_branches" ]; then
    echo "✅ Repository is ready for master → main migration!"
    echo ""
    echo "Next steps:"
    echo "  1. Follow HOW-TO-MIGRATE-MASTER-TO-MAIN.md"
    echo "  2. Run: git branch -m master main"
fi

Pre-Migration Checklist

For each repository, verify:

  • [ ] All important work is in master

  • [ ] No active development branches with unreleased features

  • [ ] Old release/version branches are cleaned up

  • [ ] Remote branches are synchronized

  • [ ] Tags are in place for any important historical points

  • [ ] Repository is in a clean state (git status clean)

Common Patterns to Clean Up

Pattern 1: Old Version Branches

# Branches like: version2, v1.0-dev, release-candidate
# Usually safe to delete if work is merged to master
git branch -d version2 v1.0-dev release-candidate

Pattern 2: Feature Branches from Pull Requests

# Branches like: feature/add-login, fix/bug-123
# Delete if already merged
git branch -d feature/add-login fix/bug-123

Pattern 3: Personal Development Branches

# Branches like: john-dev, temp-work, testing
# Archive if needed, then delete
git tag archive/john-dev john-dev
git branch -D john-dev

Pattern 4: GitFlow Branches

# Branches like: develop, release/v2.0, hotfix/critical
# Merge important work, then clean up
git checkout master
git merge develop
git branch -d develop release/v2.0

After Cleanup

Once you’ve cleaned up all branches, verify the repository is ready:

# Should show only master (and maybe a few active feature branches)
git branch -a

# Should be clean
git status

# Verify all important tags exist
git tag -l

# Check the log looks good
git log --oneline --graph --decorate -10

Now you’re ready to follow the HOW-TO-MIGRATE-MASTER-TO-MAIN.md guide!

Git Configuration Optimization

While cleaning up repositories, it’s also a good time to optimize your Git configuration for better workflows and cleaner history.

Essential Configuration for Clean Workflows

# 1. Default to 'main' branch for new repositories
git config --global init.defaultBranch main

# 2. Use rebase instead of merge for pulls (cleaner history)
git config --global pull.rebase true

# 3. Set a comfortable editor
git config --global core.editor nano  # or vim, code --wait, etc.

# 4. Configure your identity (if not already set)
git config --global user.name "Your Name"
git config --global user.email "your.email@example.com"

# 5. Enable automatic remote tracking
git config --global push.autoSetupRemote true

Configuration Analysis

pull.rebase=true - Should You Keep It?

✅ RECOMMENDED: Keep this setting

What it does:

  • git pull becomes git fetch + git rebase instead of git fetch + git merge

  • Creates linear history without unnecessary merge commits

  • Perfect for solo development and simple workflows

Benefits:

  • Cleaner commit history

  • Easier to follow project timeline

  • Reduces “Merge branch ‘master’ of origin/master” noise

  • Better for repository cleanup and migration

Example difference:

Without rebase (creates merge commits):

* Merge branch 'master' of origin/master
|\
| * Remote commit
* | Your commit  
|/
* Previous commit

With rebase (clean linear history):

* Your commit (rebased on top)
* Remote commit
* Previous commit

init.defaultBranch=main - Modern Standard

✅ RECOMMENDED: Essential for new repositories

# Verify this is set
git config --global init.defaultBranch
# Should return: main

# If not set:
git config --global init.defaultBranch main

Benefits:

  • New repositories automatically use main instead of master

  • Consistent with modern Git hosting services

  • Aligns with the migration you’re planning

Additional Helpful Settings

# Auto-prune deleted remote branches during fetch
git config --global fetch.prune true

# Use more verbose output for status
git config --global status.showUntrackedFiles all

# Enable colored output
git config --global color.ui auto

# Set default merge tool (optional)
git config --global merge.tool vimdiff  # or meld, vscode, etc.

# Configure push behavior
git config --global push.default current

Configuration for Multiple Repositories

If you have repositories that need different behaviors:

# Set repository-specific config (run inside specific repo)
cd /path/to/special/repo
git config pull.rebase false  # Override global setting for this repo
git config branch.master.rebase false  # Specific branch override

Verification Commands

After updating configuration:

# Verify your global Git config
git config --global --list | sort

# Test in a new repository
mkdir test-config
cd test-config
git init
git branch  # Should show 'main' as default

# Test pull.rebase behavior
git remote add origin https://github.com/user/repo.git
git pull origin main  # Should rebase, not merge

Why This Matters for Cleanup and Migration

During repository cleanup and migration:

  1. pull.rebase=true makes resolving conflicts easier:

    git pull origin master  # Automatically rebases your changes
    # Instead of creating merge commits during sync
    
  2. init.defaultBranch=main prevents confusion:

    git init new-project  # Automatically creates 'main' branch
    # Consistent with your migration goals
    
  3. Clean configuration reduces friction:

    • Fewer merge commits to clean up

    • Consistent branch naming

    • Smoother multi-repository workflows

Configuration Audit Script

Save as audit-git-config.sh:

#!/bin/bash
echo "=== GIT CONFIGURATION AUDIT ==="
echo ""

echo "📋 Current Global Configuration:"
git config --global --list | sort | sed 's/^/  /'
echo ""

echo "🔍 Key Settings Analysis:"

# Check pull.rebase
rebase_setting=$(git config --global pull.rebase 2>/dev/null || echo "not set")
echo "  pull.rebase: $rebase_setting"
if [ "$rebase_setting" = "true" ]; then
    echo "    ✅ Good: Uses rebase for cleaner history"
elif [ "$rebase_setting" = "false" ]; then
    echo "    ⚠️  Consider: Creates merge commits on pull"
else
    echo "    ❌ Consider setting: git config --global pull.rebase true"
fi

# Check default branch
default_branch=$(git config --global init.defaultBranch 2>/dev/null || echo "not set")
echo "  init.defaultBranch: $default_branch"
if [ "$default_branch" = "main" ]; then
    echo "    ✅ Good: New repos will use 'main'"
elif [ "$default_branch" = "master" ]; then
    echo "    ⚠️  Consider: Still using 'master' for new repos"
else
    echo "    ❌ Consider setting: git config --global init.defaultBranch main"
fi

# Check user identity
user_name=$(git config --global user.name 2>/dev/null || echo "not set")
user_email=$(git config --global user.email 2>/dev/null || echo "not set")
echo "  user.name: $user_name"
echo "  user.email: $user_email"

if [ "$user_name" = "not set" ] || [ "$user_email" = "not set" ]; then
    echo "    ❌ Set your identity:"
    echo "      git config --global user.name 'Your Name'"
    echo "      git config --global user.email 'you@example.com'"
fi

echo ""
echo "💡 Recommended optimizations:"
echo "  git config --global pull.rebase true"
echo "  git config --global init.defaultBranch main"
echo "  git config --global fetch.prune true"
echo "  git config --global push.autoSetupRemote true"

Integration with Repository Cleanup

Best practice workflow:

  1. Audit and optimize Git configuration (using above)

  2. Run repository cleanup (using existing scripts)

  3. Perform master → main migration (using migration guide)

  4. Verify everything works with optimized settings

This ensures your Git configuration supports clean workflows throughout the cleanup and migration process.

Tips for Multiple Repositories

1. Create a Repository Inventory

# List all your git repositories
find /home/billf/devel -name ".git" -type d | while read repo; do
    cd "$(dirname "$repo")"
    echo "Repository: $(pwd)"
    git branch -a 2>/dev/null | grep -E "(master|main)" | head -1
    echo ""
done

2. Batch Process

# Run cleanup analysis on all repos
for repo in /home/billf/devel/*/; do
    if [ -d "$repo/.git" ]; then
        echo "=== $(basename $repo) ==="
        cd "$repo"
        ./cleanup-before-migration.sh .
        echo ""
    fi
done

3. Prioritize Repositories

  1. Active projects (daily use) - Clean up first

  2. Important archives (occasional use) - Clean up carefully

  3. Old experiments (rarely used) - Quick cleanup or archive

Remember: It’s better to over-communicate and over-backup than to lose important work during cleanup!