Created
February 24, 2020 15:20
-
-
Save danielhanold/1bf84fdf9c27961fc4a69e5683542ee3 to your computer and use it in GitHub Desktop.
Convert SVN repos to Git and upload to GitHub
This file contains 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 | |
# Determine target directory. | |
TARGET_DIR=$1 | |
# Determine if this is the final processing, i.e. create all Git branches, | |
# tags, and garbage-collect. | |
PROCESS_MODE=${2:-FETCH_ONLY} | |
# Determine default domain for unmapped authors. | |
EMAIL_DOMAIN=${3:-example.com} | |
# Set authors file location. | |
AUTHORS_FILE=$4 | |
# Define current directory as location for authors program. | |
AUTHORS_PROGRAM_DEFAULT="$(pwd)/authors-prog.sh" | |
# Set authors program for any unmapped authors. | |
AUTHORS_PROGRAM=${5:-$AUTHORS_PROGRAM_DEFAULT} | |
# Optionally, set a starting revision to reduce the size of the Git repository. | |
STARTING_REVISION=${6:-0} | |
# Optionally, disable deleting the temporary directory for uploading to GitHub. | |
DELETE_TEMP_DIRECTORY=${7:-TRUE} | |
# Determine log filename. | |
SCRIPT_START=$(date +%s) | |
echo "Process Mode: $PROCESS_MODE" | |
echo "Target Directory: $TARGET_DIR" | |
echo "Authors Program: $AUTHORS_PROGRAM" | |
echo "Email Domain: $EMAIL_DOMAIN" | |
echo "Authors File: $AUTHORS_FILE" | |
echo "Script start (UNIX): $SCRIPT_START ($(date))" | |
# Switch to target directory. | |
cd $TARGET_DIR | |
# Kick off import. | |
if [ -f "$AUTHORS_FILE" ] | |
then | |
export GIT_EMAIL_DOMAIN=$EMAIL_DOMAIN | |
git svn fetch \ | |
--authors-file=$AUTHORS_FILE \ | |
--authors-prog=$AUTHORS_PROGRAM \ | |
--revision=$STARTING_REVISION:HEAD | |
else | |
git svn fetch \ | |
--revision=$STARTING_REVISION:HEAD | |
fi | |
# If this isn't the first time this script runs, fast-forward the actual commits. | |
git svn rebase | |
prepare_for_github() { | |
local GIT_DIR=$1 | |
local PREVIOUS_DIR=$(pwd) | |
echo "Switching into $1" | |
cd $1 | |
# Create a true Git branch for every "ref" that's not a tag. | |
# Exclude: master branch, trunk, branches starting with "trunk", branches containing special character "%" | |
git for-each-ref --format="%(refname:short)" refs/remotes/origin | sed 's#origin/##' | grep -v '^tags' | grep -v '^trunk' | grep -v 'master' | grep -v '%' | | |
while read BRANCH_NAME | |
do | |
echo "Create branch name: $BRANCH_NAME" | |
git branch $BRANCH_NAME origin/$BRANCH_NAME | |
done | |
# Create true Git tags for all tags. | |
# Exclude: the "origin/tags/tags" tag | |
git for-each-ref --format="%(refname:short)" refs/remotes/origin/tags/ | grep -v 'origin/tags/tags' | | |
while read tag | |
do | |
GIT_COMMITTER_DATE="$(git log -1 --pretty=format:"%ad" "$tag")" | |
GIT_COMMITTER_EMAIL="$(git log -1 --pretty=format:"%ce" "$tag")" | |
GIT_COMMITTER_NAME="$(git log -1 --pretty=format:"%cn" "$tag")" | |
git tag -a -m "$(git for-each-ref --format="%(contents)" "$tag")" "$(echo "$tag" | sed 's#svn/tags/##')" "$tag" || exit 1 | |
done | |
# Delete all local branches that have already been merged into master, | |
# i.e. are neither ahead or behind master. | |
git branch --merged master | grep -v 'master$' | | |
while read merged_branch_name | |
do | |
git branch -d $merged_branch_name | |
done | |
# Garbage-collect | |
git svn gc | |
git gc --aggressiv | |
# Switch back to previous directory. | |
cd $PREVIOUS_DIR | |
} | |
if [ "$PROCESS_MODE" == "PREPARE_CURRENT_FOR_GITHUB" ] | |
then | |
prepare_for_github $TARGET_DIR | |
elif [ "$PROCESS_MODE" == "CREATE_TEMP_AND_PUSH_TO_GITHUB" ] | |
then | |
# Create temporary directory and process files in directory. | |
REPO_TEMP=$(mktemp -d) | |
# Delete temporary files when program exits. | |
if [ "$DELETE_TEMP_DIRECTORY" == "TRUE" ] | |
then | |
echo "Temporary directory $REPO_TEMP will be deleted." | |
trap "exit 1" HUP INT PIPE QUIT TERM | |
trap "rm -rf $REPO_TEMP" EXIT | |
else | |
echo "Temporary directory $REPO_TEMP will not be deleted." | |
fi | |
# Rsync all files into separate directory | |
rsync -a --stats ${TARGET_DIR}/ ${REPO_TEMP} | |
# Create all branches in temporary directory. | |
prepare_for_github ${REPO_TEMP} | |
# Upload everything from temporary directory if | |
# 1. Key agent has at least 1 identity and is running and | |
# 2. Git remote is added to the repo | |
if ssh-add -l && git remote show origin | |
then | |
git -C $REPO_TEMP push --all --force | |
git -C $REPO_TEMP push --tags --force | |
else | |
echo "Either remote is not set up successfully or SSH key is not working." | |
fi | |
fi | |
# Log end date. | |
SCRIPT_END=$(date +%s) | |
echo "Script end (UNIX): $SCRIPT_END ($(date))" | |
SCRIPT_DURATION=$((($SCRIPT_END-$SCRIPT_START)/60)) | |
echo "Migration took $SCRIPT_DURATION minutes." |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment