Created
November 16, 2024 04:44
-
-
Save CJHarmath/ff1af5a66b4582541b4bb997166d998b to your computer and use it in GitHub Desktop.
svn to git migration
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# SVN to Git Migration Script | |
# ========================== | |
# | |
# This script performs a complete migration from SVN to Git while preserving | |
# history, usernames, branches, and tags. | |
# | |
# Usage: | |
# ./svn-to-git-migrate.sh <SVN_REPO_URL> <GIT_REPO_NAME> | |
# | |
# Examples: | |
# ./svn-to-git-migrate.sh http://svn.example.com/repo my-project | |
# ./svn-to-git-migrate.sh svn://svn.example.com/repo/trunk project-name | |
# ./svn-to-git-migrate.sh file:///path/to/local/svn/repo local-project | |
# | |
# Prerequisites: | |
# - git | |
# - git-svn | |
# - svn | |
# | |
# The script will: | |
# 1. Create an authors mapping file (authors.txt) | |
# 2. Convert SVN history to Git format | |
# 3. Convert SVN branches and tags to Git format | |
# 4. Create a server-ready Git repository | |
# 5. Provide instructions for pushing to GitHub/GitLab | |
# | |
# Important Notes: | |
# - Review authors.txt before proceeding with migration | |
# - Ensure sufficient disk space (at least 2x the SVN repository size) | |
# - Large repositories may take several hours to migrate | |
# - The script assumes standard SVN layout (trunk/branches/tags) | |
# - Have your GitHub/GitLab repository URL ready for the final push | |
# | |
# Output: | |
# - authors.txt: SVN to Git username mapping | |
# - migration.log: Detailed migration log | |
# - temp_migration/: Temporary working directory | |
# - <GIT_REPO_NAME>.git/: Final server-ready Git repository with complete history | |
# | |
# Post-Migration: | |
# The script will provide instructions for pushing to GitHub/GitLab: | |
# 1. Create an empty repository on GitHub/GitLab (DO NOT initialize with README) | |
# 2. Follow the provided commands to push all branches and tags | |
# | |
# Example authors.txt format: | |
# svnuser = Git User <[email protected]> | |
# john = John Doe <[email protected]> | |
# | |
set -e | |
SVN_REPO_URL="" | |
GIT_REPO_NAME="" | |
AUTHORS_FILE="authors.txt" | |
TEMP_DIR="temp_migration" | |
LOG_FILE="migration.log" | |
# Function to show usage | |
show_usage() { | |
grep '^#' "$0" | tail -n +2 | cut -c 3- | |
exit 1 | |
} | |
# Function to log messages | |
log_message() { | |
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE" | |
} | |
# Function to verify prerequisites | |
check_prerequisites() { | |
log_message "Checking prerequisites..." | |
# Check for required commands | |
commands=("git" "git-svn" "svn") | |
for cmd in "${commands[@]}"; do | |
if ! command -v "$cmd" >/dev/null 2>&1; then | |
log_message "ERROR: $cmd is not installed" | |
exit 1 | |
fi | |
done | |
} | |
# Function to create authors file | |
create_authors_file() { | |
log_message "Creating authors mapping file..." | |
if [ -f "$AUTHORS_FILE" ]; then | |
log_message "Authors file already exists, skipping..." | |
return | |
} | |
svn log -q "$SVN_REPO_URL" | \ | |
awk -F '|' '/^r/ {sub("^ ", "", $2); sub(" $", "", $2); print $2}' | \ | |
sort -u | \ | |
while read -r author; do | |
echo "$author = $author <[email protected]>" | |
done > "$AUTHORS_FILE" | |
log_message "AUTHORS_FILE created. Please review and update email addresses!" | |
exit 1 | |
} | |
# Function to display post-migration instructions | |
show_post_migration_instructions() { | |
local repo_name="$1" | |
echo | |
echo "=== Post-Migration Instructions ===" | |
echo | |
echo "Your repository is ready! Follow these steps to push to GitHub or GitLab:" | |
echo | |
echo "1. Create a new empty repository on GitHub or GitLab" | |
echo " - DO NOT initialize it with a README, license, or .gitignore" | |
echo " - GitHub: Click 'New' at github.com/yourname?tab=repositories" | |
echo " - GitLab: Click 'New project' at gitlab.com/projects/new" | |
echo | |
echo "2. Push the repository (replace REMOTE_URL with your GitHub/GitLab URL):" | |
echo | |
echo " cd ${repo_name}.git" | |
echo " # For GitHub:" | |
echo " git remote add origin https://github.com/YOUR_USERNAME/${repo_name}.git" | |
echo " # OR for GitLab:" | |
echo " git remote add origin https://gitlab.com/YOUR_USERNAME/${repo_name}.git" | |
echo | |
echo " # Push all branches and tags:" | |
echo " git push origin --all" | |
echo " git push origin --tags" | |
echo | |
echo "3. Verify the migration:" | |
echo " - Check the repository on GitHub/GitLab" | |
echo " - Verify branches and tags are present" | |
echo " - Review commit history" | |
echo " - Clone a fresh copy and check the contents:" | |
echo " git clone https://github.com/YOUR_USERNAME/${repo_name}.git" | |
echo | |
echo "4. Clean up local migration files (optional):" | |
echo " cd .." | |
echo " rm -rf temp_migration" | |
echo " # Keep ${repo_name}.git if you want a local backup" | |
echo | |
echo "Migration log is available in: migration.log" | |
echo | |
} | |
# Function to perform the migration | |
perform_migration() { | |
log_message "Starting migration process..." | |
# Create and enter temporary directory | |
mkdir -p "$TEMP_DIR" | |
cd "$TEMP_DIR" | |
# Initialize git-svn | |
log_message "Initializing git-svn..." | |
git svn init "$SVN_REPO_URL" --no-metadata \ | |
--authors-file="../$AUTHORS_FILE" \ | |
--trunk=trunk \ | |
--tags=tags \ | |
--branches=branches \ | |
--prefix=origin/ | |
# Fetch SVN repository | |
log_message "Fetching SVN repository (this may take a while)..." | |
git svn fetch | |
# Fix tags | |
log_message "Converting SVN tags to Git tags..." | |
git for-each-ref refs/remotes/origin/tags | cut -d / -f 5- | \ | |
while read -r tag; do | |
git tag "$tag" "origin/tags/$tag^" || true | |
git branch -r -d "origin/tags/$tag" || true | |
done | |
# Fix branches | |
log_message "Converting SVN branches to Git branches..." | |
git for-each-ref refs/remotes/origin | cut -d / -f 4- | \ | |
while read -r branch; do | |
if [ "$branch" != "trunk" ]; then | |
git branch "$branch" "refs/remotes/origin/$branch" || true | |
git branch -r -d "origin/$branch" || true | |
fi | |
done | |
# Create master from trunk | |
log_message "Creating master branch from trunk..." | |
git branch -m trunk master | |
# Clean up | |
log_message "Cleaning up..." | |
git gc --aggressive | |
git prune | |
# Create server-ready repository | |
log_message "Creating server-ready repository with complete history..." | |
cd .. | |
git clone --bare "$TEMP_DIR" "$GIT_REPO_NAME.git" | |
# Verify repository integrity | |
cd "$GIT_REPO_NAME.git" | |
log_message "Verifying repository integrity..." | |
git fsck --full | |
log_message "Migration completed successfully! Repository is ready for GitHub/GitLab." | |
# Return to original directory | |
cd .. | |
# Show instructions for pushing to GitHub/GitLab | |
show_post_migration_instructions "$GIT_REPO_NAME" | |
} | |
# Main execution | |
main() { | |
# Show usage if --help flag is passed or no arguments provided | |
if [ "$1" = "--help" ] || [ "$1" = "-h" ] || [ -z "$1" ] || [ -z "$2" ]; then | |
show_usage | |
fi | |
SVN_REPO_URL="$1" | |
GIT_REPO_NAME="$2" | |
# Initialize log file | |
echo "=== Migration Log Started $(date) ===" > "$LOG_FILE" | |
check_prerequisites | |
create_authors_file | |
perform_migration | |
} | |
main "$@" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment