Skip to content

Instantly share code, notes, and snippets.

@goncalomb
Last active January 19, 2021 00:07
Show Gist options
  • Save goncalomb/13f28e459fe4dd656e8b43f92c826140 to your computer and use it in GitHub Desktop.
Save goncalomb/13f28e459fe4dd656e8b43f92c826140 to your computer and use it in GitHub Desktop.
Bash script to find problems with git repositories.
#!/bin/bash
# Author: Gonçalo Baltazar <[email protected]>
# I place this code in the public domain.
# Finds problems with git repositories that might lead to information loss
# in case of losing the local copy.
# Things like: uncommitted changes, untracked files, commits not pushed, etc.
# Put this script on your PATH. Then run 'git-problems' on a git repository or
# directory with multiple repositories.
# Tested on Linux Mint.
function error-msg {
if [ -z "$ERROR" ]; then echo; fi
ERROR="TRUE"
echo -e " \x1b[33m$1\x1b[0m"
}
HOME_IS_HERE=""
if [ "$HOME" = "$(pwd -P)" ]; then
HOME_IS_HERE="true"
fi
for GIT_DIR in $(find . -type d -name .git -prune | sort 2>/dev/null); do (
WORKSPACE_DIR=$(dirname -- "$GIT_DIR")
cd "$WORKSPACE_DIR"
if [ "$WORKSPACE_DIR" = "." ]; then
echo -en "(this repository):"
elif [ -n "$HOME_IS_HERE" ]; then
echo -en "~${WORKSPACE_DIR:1}:"
else
echo -en "$WORKSPACE_DIR:"
fi
ERROR=""
#git update-index -q --refresh
#if git rev-parse HEAD 1>/dev/null 2>/dev/null && ! git diff-index --quiet HEAD; then
if ! (git diff --quiet && git diff --cached --quiet); then
error-msg "Workspace has uncommitted changes"
fi
if [ -n "$(git ls-files --exclude-standard --others)" ]; then
error-msg "Workspace has untracked files"
fi
if ! git symbolic-ref HEAD 1>/dev/null 2>/dev/null ; then
error-msg "HEAD detached at $(git rev-parse --short HEAD)"
fi
STASH_COUNT=$(git stash list 2> /dev/null | wc -l | tr -d ' ')
if [ "$STASH_COUNT" != "0" ]; then
error-msg "The stash has $STASH_COUNT entry(ies)"
fi
while read CODE; do
eval $CODE
if [ -z "$REMOTE" ]; then
error-msg "'$LOCAL' has no tracking branch"
else
LOCAL_REV=$(git rev-parse "$LOCAL")
REMOTE_REV=$(git rev-parse "$REMOTE")
MERGE_BASE_REV=$(git merge-base "$LOCAL" "$REMOTE")
if [ "$LOCAL_REV" = "$REMOTE_REV" ]; then
: # branch up-to-date
elif [ "$LOCAL_REV" = "$MERGE_BASE_REV" ]; then
error-msg "'$LOCAL' is behind '$REMOTE' by $(git rev-list $LOCAL_REV...$REMOTE_REV --count) commit(s)"
elif [ "$REMOTE_REV" = "$MERGE_BASE_REV" ]; then
error-msg "'$LOCAL' is ahead of '$REMOTE' by $(git rev-list $LOCAL_REV...$REMOTE_REV --count) commit(s)"
else
error-msg "'$LOCAL' and '$REMOTE' have diverged"
fi
fi
done < <(git for-each-ref --format="LOCAL=\"%(refname:short)\"; REMOTE=\"%(upstream:short)\"" "refs/heads")
if [ -z "$ERROR" ]; then
echo -e " \x1b[32mOK\x1b[0m"
fi
) done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment