Skip to content

Instantly share code, notes, and snippets.

@schnell18
Last active December 29, 2015 09:39
Show Gist options
  • Save schnell18/7651891 to your computer and use it in GitHub Desktop.
Save schnell18/7651891 to your computer and use it in GitHub Desktop.
This script is sample Subversion to Git migration scripts to perform references relocation, bad commit message fix, lost merge history restore etc.
#!/bin/bash
# This script should be launched under the top level git directory.
function clean_up() {
rm -fr .git/svn
rm -fr .git/info/grafts
git branch -d trunk
git gc
}
function uplift_refs() {
for entry in $(git for-each-ref --format="%(objectname)|%(refname)")
do
oldref=$(echo $entry | cut -d '|' -f 2)
if [[ $oldref =~ remotes ]]
then
sha=$(echo $entry | cut -d '|' -f 1)
if [[ $oldref =~ remotes/tags ]]
then
newref=$(echo $oldref | sed -e 's/remotes\/tags/tags/')
elif [[ $oldref =~ remotes ]]
then
newref=$(echo $oldref | sed -e 's/remotes/heads/')
fi
if [[ $newref =~ br_alt_excel ]]
then
newref=${newref//br_alt_excel/alt_excel}
fi
git update-ref $newref $sha
git update-ref -d $oldref
fi
done
}
function generate_filters() {
# generate filter script for removing unnecessary files
cat << EOF > /tmp/rm_bad_files.sh
git rm --cached -r --ignore-unmatch testcase/{TestResult,UCA_EE_Parser_Test*};
git rm --cached -r --ignore-unmatch doc/{*.docx,*.doc}
EOF
# generate filter script for fixing commit message
cat << 'EOF' > /tmp/fix_commit_msg.sh
perl -e 'while(<>) {print join(q/: /, split(/\s*:\s*/, $_, 2))}'
EOF
chmod +x /tmp/rm_bad_files.sh
chmod +x /tmp/fix_commit_msg.sh
}
function remove_filters() {
rm /tmp/rm_bad_files.sh
rm /tmp/fix_commit_msg.sh
}
function fix_commit_history() {
generate_filters
git filter-branch \
--tag-name-filter cat \
--index-filter /tmp/rm_bad_files.sh \
--msg-filter /tmp/fix_commit_msg.sh \
-- --all
git for-each-ref --format="%(refname)" refs/original/ \
| xargs -n 1 git update-ref -d
remove_filters
}
function usage() {
cat << EOF
Subversion to Git migration automation tool(v1.0beta)
This tool automates the process to fix, cleanup after
the repository is migrated from subversion with git-svn.
Usage:
post_migration.sh [-g <grafts_file>] [-h]
Options:
-g specify the grafts file to change parents of certain merge
commits. Each line contains: sha-1 parent1-sha[ parent2-sha1]
-h print help
EOF
}
while getopts "g:h" arg
do
case $arg in
g)
echo "$grafts_file";
grafts_file=$OPTARG
;;
h)
usage
exit 0
;;
?)
echo "Invalid argument $arg"
exit 1
;;
esac
done
git_ws_dir=$(pwd)
# validate git workspace directory
if [[ ! -d .git ]]
then
echo "Not a git directory: $git_ws_dir"
exit 1
fi
# validate grafts file
if [[ ! -e $grafts_file ]]
then
echo "Unable to find grafts file: $grafts_file"
exit 2
fi
echo "Start post-migration processing..."
if [[ (-e $grafts_file) && (-f $grafts_file) ]]
then
echo "Prepare .git/info/grafts..."
cat $grafts_file > .git/info/grafts
fi
echo "Move refs to local name space..."
uplift_refs
echo "Fix commit history..."
fix_commit_history
echo "Cleanup .git directory..."
clean_up
echo "Completed post-migration processing."
# vim: set ai nu nobk expandtab sw=4 ts=4 syntax=sh:
@schnell18
Copy link
Author

This revision moves the inline filter commands to separate shell scripts for better code readability. No functional changes are introduced.

@schnell18
Copy link
Author

Make the here doc not interpolative to generate correct perl script to tidy the commit message.

@patdong
Copy link

patdong commented Dec 16, 2013

Hi schnell18,

Today I used your script to want to amend losing merge history restore when migrating repository from SVN to Git. When I execute the script, an error thrown:

./svn_to_git_post_migration.sh: line 15: conditional binary operator expected
./svn_to_git_post_migration.sh: line 15: syntax error near =~' ./svn_to_git_post_migration.sh: line 15: if [[ $oldref =~ 'remotes' ]];
then'

My Git Bash is 1.8.3.

Thanks

@schnell18
Copy link
Author

Hi patdong,
This script is specific to my project. You can not expect it meets your need out-of-box.

Regarding the fix merge history part, you need come up the right grafts file and run the git branch-filter --tag-name-filter as in my script.

The problem you came across was reported by my colleague as well. Using a recent version of bash should resolve this problem.

Thanks for try this script and good luck with your task!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment