--- /dev/null
+#!/bin/sh
+
+# A script to recursively pull git repositories behind origin.
+
+# Copyright (c) 2022 Stefan Huber
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+
+set -e
+set -u
+
+function showHelp
+{
+ echo "Usage: $0 [-h|--help]"
+ echo " $0 [OPTIONS]"
+ echo ""
+ echo "OPTIONS:"
+ echo " -a, --ask ask user for each repo"
+ echo " -h, --help show this message"
+ echo " -n, --dry-run do not actually perform pull"
+}
+
+if ! options=$(getopt -u -o ahn -l ask,help,dry-run -- "$@"); then
+ showHelp >&2
+ exit 1
+fi
+set -- $options
+
+optDryRun=0
+optAsk=0
+
+#Parse the arguments
+while [ $# -gt 0 ]; do
+ case "$1" in
+ -h|--help) showHelp; exit 0 ;;
+ -n|--dry-run) optDryRun=1 ;;
+ -a|--ask) optAsk=1 ;;
+ --) shift; break ;;
+ -*) echo "Unrecognized option $1" >&2; showHelp >&2; exit 1 ;;
+ *) break ;;
+ esac
+ shift
+done
+
+for REPODIR in $(find "$@" -name .git -type d 2> /dev/null); do
+
+ REPO=$(dirname ${REPODIR})
+ echo "Run ${REPO}…"
+
+ if [ "${optAsk}" = 1 ]; then
+ read -p " Process [y/N]? " -n1 response
+ echo ""
+
+ [ "${response}" = "y" ] || continue
+ fi
+
+ git -C ${REPO} remote update
+
+ if [ -z "$(git -C ${REPO} status -uno | grep 'Your branch is behind')" ] ; then
+ echo -e "\e[1;32m Already up to date\e[0m"
+ else
+ [ "${optDryRun}" = 1 ] && continue
+ git -C ${REPO} pull
+ fi
+
+done