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:
Audit all branches - Identify what needs to be kept vs. deleted
Merge important work - Consolidate valuable changes
Clean up obsolete branches - Remove outdated development branches
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 workversion2: 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 codefeature/new-api: 5 commits ahead, 2 behindexperiment/ml-model: 10 commits ahead, 20 behindhotfix/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 workrelease/v1.0: Old release branchrelease/v2.0: Another old releasedevelop: 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 statusclean)
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.
Recommended Global Settings
Check your current configuration:
# See all current settings
git config --global --list
# Check specific settings
git config --global pull.rebase
git config --global init.defaultBranch
git config --global core.editor
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 pullbecomesgit fetch + git rebaseinstead ofgit fetch + git mergeCreates 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
maininstead ofmasterConsistent 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:
pull.rebase=truemakes resolving conflicts easier:git pull origin master # Automatically rebases your changes # Instead of creating merge commits during sync
init.defaultBranch=mainprevents confusion:git init new-project # Automatically creates 'main' branch # Consistent with your migration goals
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:
Audit and optimize Git configuration (using above)
Run repository cleanup (using existing scripts)
Perform master → main migration (using migration guide)
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
Active projects (daily use) - Clean up first
Important archives (occasional use) - Clean up carefully
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!