Last active
March 11, 2016 19:23
-
-
Save blitzrk/600e004c0bfb246dfe21 to your computer and use it in GitHub Desktop.
Bash (>=4.0) script for syncing SVN to git repo
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 | |
usage="\ | |
Sync svn repo to git repo in working dir or PATH | |
Usage: svn-sync.sh [OPTION]... [PATH] | |
Options: | |
-h, --help: Show this help and exit | |
-t, --tags: Import tags as well as branches | |
-v, --verbose: Show verbose output | |
-vv: Increase verbosity | |
NOTE: This tool is meant to be used after the initial 'git svn clone' | |
to keep the git repository synced. During this period of syncing, do | |
NOT make any commits to the git repo. | |
" | |
ref=`git rev-parse --abbrev-ref HEAD` | |
if [ "$ref" == "HEAD" ] | |
then | |
ref=`git describe --all 2>/dev/null || git show-ref -s --head HEAD` [57/656] | |
fi | |
# Parse arguments | |
_T=0 | |
_V=0 | |
_PATH="." | |
while [ "$#" -gt 0 ] | |
do | |
args=$1 | |
while [ -n "${args[0]}" ]; do | |
arg=${args[0]} | |
case $arg in | |
--help|-h) | |
echo "$usage" | |
exit 0 | |
;; | |
-[^-]*) | |
if [ -n "${arg//[vt-]}" ]; then | |
echo "Unknown option(s) '${arg//[vt-]}'" | |
exit 1 | |
elif [ ${#arg} -gt 2 ]; then | |
args=( `echo $arg | grep -o '[^-]' | awk '{print "-" $1}'` ) | |
continue | |
fi | |
;;& | |
--tags|-t) | |
_T=1 | |
;; | |
--verbose|-v) | |
_V=`expr $_V + 1` | |
;; | |
*) | |
if [[ "$arg" = --* ]]; then | |
echo "Unknown option '${arg//-}'" | |
exit 1 | |
fi | |
;;& | |
*) | |
if [ ! -d $arg ]; then | |
echo "'$arg' is not a directory" | |
exit 2 | |
else | |
_PATH=$1 | |
fi | |
;; | |
esac | |
args=("${args[@]:1}") | |
done | |
shift | |
done | |
# Fetch updates | |
pushd $_PATH >/dev/null | |
git svn fetch `test $_V -lt 2 && echo -q` || { echo "Fetch failed. Exiting."; exit 1; } | |
# Force update all branches, importing if necessary | |
echo "Importing branches" | |
test $_V -ge 1 && echo | |
git branch -r | | |
grep -v '/tags/' | | |
while read -r remote | |
do | |
local=${remote#*/} | |
if [ "$local" == "trunk" ]; then | |
local=master | |
fi | |
if [[ ! `git branch -q --list $local` ]]; then | |
test $_V -ge 1 && echo "Importing $remote" | |
git checkout -b $local $remote | |
elif [ `git show-ref -s refs/heads/$local` != `git show-ref -s refs/remotes/$remote` ]; then | |
test $_V -ge 1 && echo "Updating $local" | |
git checkout -q $local | |
git config merge.renamelimit 9999999 | |
git merge -q -X theirs --no-commit $remote | |
git reset -q --hard $remote # Just in case a merge commit happened (manually) | |
git config --unset merge.renamelimit | |
else | |
test $_V -ge 2 && echo "Skipping $local - already up to date" | |
fi | |
done | |
test $_V -ge 1 && echo | |
if [ $_T -eq 1 ] | |
then | |
echo "Importing tags" | |
test $_V -ge 1 && echo | |
git for-each-ref refs/remotes/origin/tags | | |
sed 's/\t/ /' | | |
cut -d ' ' -f 1,3 --output-delimiter ' ' | | |
sed 's|refs/remotes/||' | | |
while read -r line; do | |
commit=${line##* } | |
tag=${line#*tags/} | |
if git tag -l | grep ^$tag$ >/dev/null; then | |
test $_V -ge 2 && echo "Skipping $tag" | |
else | |
test $_V -ge 1 && echo "Importing $tag" | |
git checkout -q $commit && git tag $tag >/dev/null | |
fi | |
done | |
test $_V -ge 1 && echo | |
fi | |
echo "Returning to $ref" | |
git checkout -q $ref | |
popd >/dev/null |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment