Bash script to find problems with git repositories.
#!/bin/bash | |
# Author: Gonçalo Baltazar <me@goncalomb.com> | |
# 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