Skip to content

Instantly share code, notes, and snippets.

@nrutman
Last active January 19, 2022 21:44
Show Gist options
  • Save nrutman/771f4cd64683a0c9eec8efcb3cb2c9d6 to your computer and use it in GitHub Desktop.
Save nrutman/771f4cd64683a0c9eec8efcb3cb2c9d6 to your computer and use it in GitHub Desktop.
A bash script that will pull from upstream on a directory of git repositories
#!/usr/bin/env bash
# Does a git pull for every git repository in a directory and tracks the results
# Resolves a relative directory
# source: https://stackoverflow.com/questions/7126580/expand-a-possible-relative-path-in-bash
function dir_resolve()
{
cd "$1" 2>/dev/null || return $?
pwd -P
}
# prints an error message in red
function print_error()
{
printf "\x1B[91m%b\x1B[0m" "$1"
}
# prints a success message in green
function print_success()
{
printf "\x1B[32m%b\x1B[0m" "$1"
}
# prints a warning in yellow
function print_warning()
{
printf "\x1B[33m%b\x1B[0m" "$1"
}
# outputs usage
function usage()
{
echo "pull-all [directory] [search_depth]"
echo " directory Source directory to search for git repositories (defaults to current directory)"
echo " search_depth Depth to search when looking for repositories (defaults to \"2\")"
}
# catch usage cases (--help flag or no parameters)
if [ "$1" == "--help" ]; then
usage
exit 0
fi
if [ $# -eq 0 ]; then
usage
exit 0;
fi
# parameters
src_dir=$(dir_resolve "$1")
default_git_find_depth=${2:-2} # 2 by default
# utility characters
str_check="\xE2\x9C\x94" # check mark
# find the git repositories
repos=$(find "$src_dir" -type d -maxdepth "$default_git_find_depth" -name ".git" | sort | sed 's/\/\.git$//g')
#loop through the repos
for repo in $repos; do
# output the repo name
printf "\x1B[1m%s\x1B[0m" "$(basename "$repo")"
# go to the repo and do pre-pull checks
cd "$repo" || exit $?
printf " [%s]..." "$(git rev-parse --abbrev-ref HEAD)"
has_upstream=$(git status -sb | grep "\.\.\..*$")
upstream_gone=$(echo "$has_upstream" | grep "\[gone\]")
local_changes=$(git diff-index --name-only HEAD --)
if [ -z "$has_upstream" ]; then
print_warning "No upstream!\n"
continue
elif [ -n "$upstream_gone" ]; then
print_error "Upstream gone!\n"
continue
elif [ -n "$local_changes" ]; then
print_warning "Local changes exist\n"
continue
fi
# try to pull and display output
pull_output=$(git pull)
if [ "$?" != "0" ]; then
# pull failed
print_error "Error!\n"
elif [ "Already up to date." == "$pull_output" ]; then
# no changes to pull
print_success "$str_check\n" # check
elif [[ "$pull_output" =~ "Updating".* ]]; then
# we got changes
print_success "$str_check Updated!\n"
else
# something unknown happened but without an error
print_warning "???"
fi
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment