#!/bin/bash usage() { echo "Usage ${0} [[--ignore|-i] dir_name] [--main]" echo " --help Show this help" echo " --main Checkout to main branch" echo " --ignore=* Ignore folders" exit 1 } find_folders() { set -- ./ -name ".git" -type d for IGNORE_FOLDER in ${IGNORE_FOLDERS} do set -- "$@" -not -path '"*/'${IGNORE_FOLDER}'/*"' done find $@ } # Map long options to short ones and rebuild argv translated=() while (( $# )); do case "$1" in --help) translated+=("-h"); shift ;; --main) translated+=("-m"); shift ;; --ignore=*) translated+=("-i" "${1#*=}"); shift ;; --) translated+=("--"); shift; translated+=("$@"); set -- ;; *) translated+=("$1"); shift ;; esac done set -- "${translated[@]}" IGNORE_FOLDERS="" FLAG_SWITCH_TO_MAIN="" while getopts ":hmi:" opt; do case "$opt" in h) usage;; m) FLAG_SWITCH_TO_MAIN=1;; i) IGNORE_FOLDERS="${IGNORE_FOLDERS} ${OPTARG}";; :) echo "Missing arg for -$OPTARG"; usage;; \?) echo "Invalid option: -$OPTARG"; usage;; esac done for DIR in $(find_folders) do pushd ${PWD} > /dev/null echo "[DEBUG] Work with $(dirname ${DIR})" cd $(dirname ${DIR}) if [[ -n $(git status --porcelain) ]] then echo "[WARN] There are uncommitted changes." declare UNCOMMIT_CHANGES=1 git stash fi declare MASTER_BRANCH="$(git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@')" declare CURRENT_BRANCH="$(git branch --show-current)" if [[ "$MASTER_BRANCH" == "$CURRENT_BRANCH" ]] then git pull --all git remote prune origin else git checkout ${MASTER_BRANCH} git pull --all git remote prune origin if [[ -z "${FLAG_SWITCH_TO_MAIN}" ]] then git checkout ${CURRENT_BRANCH} || echo "[WARN] current brach has been deleted" fi fi git branch --merged | grep -v "^*\|${MASTER_BRANCH}" | xargs -r git branch -D if [ ! -z "$UNCOMMIT_CHANGES" ] then git stash pop fi unset UNCOMMIT_CHANGES MASTER_BRANCH CURRENT_BRANCH popd > /dev/null done