Permalink
Cannot retrieve contributors at this time
ABOUT_THIS_SCRIPT=" | |
Q: Would you lose any work if your local clone of a git repository were lost? | |
A: Run this script to find out. | |
Please see the Readme.md for more discussion. | |
License: CC BY SA [creative commons, attribution, share-alike] | |
By Ben Klemens. See http://modelingwithdata.org/arch/00000194.htm for discussion. | |
Some portions based on: | |
http://0xfe.blogspot.com/2010/04/adding-git-status-information-to-your.html | |
http://0xfe.blogspot.com/2010/04/improved-git-enabled-shell-prompt.html | |
" | |
green="\033[0;32m" | |
bold_green="\033[1;32m" | |
cyan="\033[0;36m" | |
bold_cyan="\033[1;36m" | |
red="\033[0;31m" | |
bold_red="\033[1;31m" | |
no_color="\033[0m" | |
Red_X="${bold_red}✘${no_color}" | |
Check="${bold_cyan}✓${no_color}" | |
Divider="${bold_cyan}―――${no_color}" | |
Dirty=0 | |
test "$1" = "-a" | |
Action=$? | |
onetest () { if eval $3 ; then printf "$Red_X $2\n"; Dirty=1; else printf "$Check $1\n"; fi } | |
# unpushed branches, which is the list of remote branches that are not synced to the local HEAD. | |
# Original author had: | |
## Returns "unpushed:N" where N is the number of unpushed local and remote branches (if any). | |
## local unpushed=`expr $( (git branch --no-color -r --contains $1; git branch --no-color -r) | sort | uniq -u | wc -l )` | |
# I just need to know that a given branch is contained by at least one remote. | |
# Assume the network of repos is not super-complicated so there's just the origin | |
allbranches(){ | |
for i in `git branch --no-color | grep -v "(HEAD.*)" | sed 's/\* //'`; do | |
unpushed=`expr $( (git branch --no-color -r --contains $i) | wc -l )` | |
onetest "$i pushed to origin" "$i not pushed to origin" '[ "$unpushed" = "0" -o "`git branch -r`" = "" ]' | |
if [ "$unpushed" = "0" ] || [ "`git branch -r`" = "" ] ; then | |
if [ $Action = 0 ] ; then | |
echo -n "Run git push origin $i? [y/n] " | |
read yesno | |
if [ "$yesno" != "n" -a "$yesno" != 'N' ]; then | |
git push origin $i | |
fi | |
fi | |
fi | |
done | |
} | |
# Optional test to add for unmerged branches, if that's your workflow. | |
# local unmerged=`expr $(git branch --no-color -a --no-merged | wc -l)` | |
# onetest "no unmerged files" "unmerged files" '[ "$unmerged" != "0" ]' | |
# main sequence: run each test | |
if [ "$1" = "-h" ]; then echo "Check whether a git repository can be deleted. Use -a to automatically run some next steps."; fi | |
is_repository=$(git status > /dev/null 2> /dev/null; echo $?) | |
if [ $is_repository -gt 0 ]; then | |
printf "$Red_X Not a git repository\n"; Dirty=1; | |
if [ $Action -eq 0 ] ; then | |
echo -n "Initialize repository? [y/n] " | |
read yesno | |
if [ "$yesno" != "n" -a "$yesno" != 'N' ]; then | |
git init | |
fi | |
fi | |
fi | |
if [ $is_repository -eq 0 ]; then #skip to the end if not a repository | |
Untracked=$Dirty | |
if [ $Action -eq 0 ] && [ "$Untracked" != 0 ]; then git status -s; Action=1; fi; | |
onetest "no untracked files" "untracked files" '[ `git ls-files --others --exclude-standard | wc -l` -ne 0 ]' | |
Untracked=$Dirty | |
if [ $Action = 0 ] && [ "$Untracked" != 0 ]; then git status -s; Action=1; fi; | |
onetest "no unstaged diffs" "diffs to commit" '[ "$(git diff --shortstat 2> /dev/null)" != "" -o "$(git diff --staged --shortstat 2> /dev/null)" != "" ]' | |
Diffs=$((Dirty - Untracked)) | |
if [ $Action = 0 ] && [ "$Diffs" != 0 ]; then git --no-pager diff; Action=1; fi; | |
stash=`expr $(git stash list 2>/dev/null| wc -l)` # Return the number of stashed states, not just 0|1. | |
onetest "no pending stashes" "stashes pending" '[ "$stash" != "0" ]' | |
if [ $Action = 0 ] && [ "$stash" != "0" ] ; then | |
if [ $stash -eq 1 ]; then | |
git --no-pager stash show -p | |
elif [ $stash != 0 ]; then | |
git stash list | |
fi | |
Action=1 | |
fi | |
unpushed_tags=`git show-ref --tags | grep -v -F "$(git ls-remote --tags origin | grep -v '\^{}' | cut -f 2)" | sed 's#.*tags/##'` | |
onetest "no unpushed tags" "unpushed tags: $unpushed_tags" '[ ! -z "$unpushed_tags" ]' | |
if [ $Action = 0 ] && [ ! -z "$unpushed_tags" ] ; then | |
echo -n "Push all tags? [y/n] " | |
read yesno | |
if [ "$yesno" != "n" -a "$yesno" != 'N' ]; then | |
git push --tags | |
fi | |
Action=1 | |
fi | |
detached=`grep -v "^ref" "$(git rev-parse --show-toplevel)/.git/HEAD" |wc -l` | |
onetest "head attached" "detached head" '[ $detached -gt 0 ]' | |
if [ $Action = 0 ] && [ $detached -gt 0 ] ; then | |
if [ $detached -eq 1 ]; then | |
echo -n "Merge detached head into master? [y/n] " | |
read yesno | |
if [ "$yesno" != "n" -a "$yesno" != 'N' ]; then | |
git checkout -b HEADregraft | |
git commit -m "Check in HEAD to merge" | |
git checkout master | |
git merge HEADregraft | |
git branch -d HEADregraft | |
fi | |
Action=1 | |
else | |
echo "Multiple detached HEADs. This is biologically impossible." | |
fi | |
fi | |
allbranches | |
# run this very program foreach submodule | |
if [ -e "`git rev-parse --show-toplevel`/.gitmodules" ] ; then | |
echo -e "${Divider}Checking submodules" | |
if [ $Action = 0 ] ; then | |
git submodule foreach "$0 -a" | |
else | |
git submodule foreach "$0" | |
fi | |
Subdirty=$? | |
Dirty=$((Dirty + $Subdirty)) | |
#else: submodules are so infrequently used, don't even mention this test if no .gitmodules. | |
#$onetest "no submodules to check" "--" false | |
fi | |
#OK, checks done. Check to remove working directory | |
if [ "$1" = "-a" ] && [ "$Dirty" = 0 ]; then | |
WD="`git rev-parse --show-toplevel`" | |
echo -n "Removing $WD. OK? [y/n] " | |
read yesno | |
if [ "$yesno" != "n" -a "$yesno" != 'N' ]; then | |
cd "$WD/.." | |
rm -rf "$WD" | |
fi | |
fi | |
fi #if isnt_repository we skipped almost all of the above | |
[ $Dirty -eq 0 ] #return value |