Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save codeinthehole/eb39e5b2238aca79ca68d48ded32d599 to your computer and use it in GitHub Desktop.
Save codeinthehole/eb39e5b2238aca79ca68d48ded32d599 to your computer and use it in GitHub Desktop.
Bash script for checking local repositories for unpushed changes
#!/usr/bin/env bash
#
# Check the status of a folder of repos to see if there are any unpushed commits.
#
# This is intended to help migrate to a new laptop, where you want to check
# that there are no unpushed local commits before switching to the new machine.
#
# Needs `rg` and `fd` installed.
set -e
function check_all_repos {
local base_dir="$1"
repo_folders "$base_dir" | while read -r repo; do
folder_name="$(basename "$repo")"
echo "Checking repo '$folder_name'..."
cd "$repo" || exit 1
check_repo
done
}
# Return the full paths to repos to examine.
function repo_folders {
fd -t d -d 1 . "$1"
}
# Check the status of the repo.
function check_repo {
# Update local index.
#git fetch 2> /dev/null
# Loop over local branches and check if they are in sync.
branches_to_check | while read -r branch; do
tracking_branch=$(remote_tracking_branch "$branch")
if [ -z "$tracking_branch" ]; then
echo " No tracking branch for '$branch'" >&2
else
if is_out_of_sync "$branch" "$tracking_branch"; then
echo " Branch '$branch' is out of sync" >&2
fi
fi
done
}
# Return the branches to check.
function branches_to_check {
# All branches except mainlines.
git branch --format='%(refname:short)' | rg -v "^(master|main|production)$"
}
# Print the name of the remote tracking branch (or an empty string).
function remote_tracking_branch {
if name=$(git rev-parse --abbrev-ref "$1@{upstream}" 2>/dev/null)
then
echo "$name"
else
echo ""
fi
}
# Test if the two branches are out of sync with each other.
function is_out_of_sync {
local local_branch="$1"
local tracking_branch="$2"
ahead=$(git rev-list --count "$local_branch...$tracking_branch")
behind=$(git rev-list --count "$tracking_branch...$local_branch")
[ "$ahead" -ne 0 ] || [ "$behind" -ne 0 ]
}
# Pass in the parent folder where the repos live.
check_all_repos "$HOME/Workspace/octo/"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment