Skip to content

Instantly share code, notes, and snippets.

@mgoellnitz
Last active December 9, 2021 00:35
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mgoellnitz/a3842286e1b68f039c98f9cb46026465 to your computer and use it in GitHub Desktop.
Save mgoellnitz/a3842286e1b68f039c98f9cb46026465 to your computer and use it in GitHub Desktop.
GIT recovery support script to easily set some defaults when (re-)cloning a set of repositories
#!/bin/bash
#
# Copyright 2016-2021 Martin Goellnitz
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# This script relies on a git.repositoris file residing in $(pwd)
if [ ! -f git.repositories ] ; then
echo "No file git.repository with descriptions of the repositories to recover found."
exit
fi
#
# Format:
# [name FIRST_NAME LAST_NAME]
# [mail MAIL_ADDRESS]
# [push PUSH_MODE]
# REPO_DIR_NAME GIT_URL
# [remote REMOTE_NAME GIT_URL]
# [track BRANCH REMOTE_NAME REMOTE_BRANCH]
# [branch BRANCH]
# [# comment]
#
# Empty lines allowed - no comments
# Mail and name must be set before the repo line, remotes are added subsequently.
# push mode, mail, and name are inhertied by subsequent repo descriptions and can changed
# for the following repos anywhere in the description file.
#
# If you are using submodules, another file named git.remotes can be added.
# It allows you to define multiple remotes for submodules. The format is line
# by line:
#
# origin remote|remoteurl
#
# with the following details:
# origin: url without leading "https" or "git@"
# remote: local name of the remote
# remoteurl: full url of the remote including all elements like "git@" or "https://"
#
REPO=$1
CWD=`pwd`
PUSH="simple"
INREPO="false"
while IFS='' read -r line || [[ -n "$line" ]]; do
# echo " line: $line"
values=($line)
# echo "trigger ${values[0]}"
case ${values[0]} in
"#")
;;
"push")
PUSH="${values[1]}"
;;
"mail")
MAIL="${values[1]}"
;;
"name")
NAME="${values[1]} ${values[2]}"
;;
"remote")
if [ "$INREPO" = "true" ] ; then
if [ $(git remote |grep ${values[1]}|wc -l) == 0 ] ; then
git remote add ${values[1]} ${values[2]}
else
if [ -z "$REPO" ] ; then
echo "Remote ${values[1]} already configured"
else
REMOTE=$(git remote get-url ${values[1]})
if [ "$REMOTE" != "${values[2]}" ] ; then
git remote set-url ${values[1]} ${values[2]}
fi
fi
fi
fi
;;
"track")
if [ "$INREPO" = "true" ] ; then
if [ "$(git branch -l|grep "${values[1]}")|wc -l" == "0" ] ; then
git fetch ${values[2]}
git checkout -b ${values[1]} --track ${values[2]}/${values[3]}
git rebase
git checkout master
fi
fi
;;
"branch")
if [ "$INREPO" = "true" ] ; then
git checkout ${values[1]}
fi
;;
*)
if [ ! -z ${values[0]} ] ; then
cd $CWD
INREPO="false"
if [ ! -d ${values[0]}/.git ] ; then
if [ -z "$REPO" ] || [ "${values[0]}" = "$REPO" ] ; then
echo "Fetch repo ${values[0]}"
INREPO="true"
git clone ${values[1]} ${values[0]}
if [ -d "${values[0]}" ] ; then
cd ${values[0]}
git config --local user.email $MAIL
git config --local user.name "$NAME"
git config --local push.default $PUSH
rm -f .git/hooks/*.sample
if [ -f ".gitmodules" ] ; then
git submodule update --init --recursive
BASE="$(pwd)"
for iter in $(git submodule |cut -d ' ' -f 3,4) ; do
if [ -z "$module" ] ; then
module=$iter
else
branch=$(echo $iter|tr -d '()'|cut -d '/' -f 2)
cd $module
echo "$module ($branch)"
git config --local user.email "$MAIL"
git config --local user.name "$NAME"
git config --local push.default "$PUSH"
git checkout $branch
REF=$(git remote get-url origin|sed -e 's/https:..//g'|cut -d '@' -f 2)
for r in $(grep "$REF" $BASE/../git.remotes|cut -d ' ' -f 2); do
echo " $(echo "$r"|cut -d '|' -f 1) $(echo "$r"|cut -d '|' -f 2)"
git remote add "$(echo "$r"|cut -d '|' -f 1)" "$(echo "$r"|cut -d '|' -f 2)"
done
cd $BASE
module=
fi
done
fi
else
echo "Cannot clone repository ${values[0]}"
exit 1
fi
fi
else
if [ -z "$REPO" ] ; then
echo "${values[0]} already exists"
fi
cd ${values[0]}
INREPO="true"
fi
fi
;;
esac
done < git.repositories
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment