Skip to content
Permalink
master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
executable file 112 lines (105 sloc) 3 KB
#!/bin/bash
# Source: http://stackoverflow.com/questions/13064613/git-how-to-prune-local-tracking-branches-that-do-not-exist-on-remote-anymore
contains()
{
needle=$1
shift
for elem
do
[ "$needle" = "$elem" ] && return 0
done
return 1
}
printUsage()
{
cat <<HELPTEXT
Remove old local branches that do not exist in ${remote:-REMOTE} any more.
Leaves local branches that have never been published to ${remote:-REMOTE} intact.
With --test, only print which local branches would be deleted.
Note: To do this automatically on each fetch / pull:
git config --global fetch.prune true
HELPTEXT
echo
printf 'Usage: %q %s\n' "$(basename "$1")" "${remote:-REMOTE} [-t|--test|-f|--force] [-?|-h|--help]"
echo
cat <<HELPTEXT
Remove old branches in ${remote:-REMOTE} that have no corresponding local branch any
longer.
With --test, only print which ${remote:-REMOTE} branches would be deleted.
HELPTEXT
echo
printf 'Usage: %q %s\n' "$(basename "$1")" "${remote:-REMOTE} -R|--reverse [-t|--test|-f|--force] [-y|--yes]"
}
case "$1" in
--help|-h|-\?) shift; printUsage "$0"; exit 0;;
--no-color|--color=*)
shift;;
--color) shift; shift;;
esac
remote="${1:?}"; shift
action=
branchDeleteOption=-d
isReverse=
typeset -a gitRemoteMutateArgs=()
while [ $# -ne 0 ]
do
case "$1" in
--help|-h|-\?) shift; printUsage "$0"; exit 0;;
--no-color|--color=*)
shift;;
--color) shift; shift;;
--reverse|-R) shift; isReverse=t;;
--force|-f) shift; branchDeleteOption=-D;;
--yes|-y) gitRemoteMutateArgs+=("$1"); shift;;
--test|-t) shift; action=dryRun;;
--) shift; break;;
-*) { echo "ERROR: Unknown option \"$1\"!"; echo; printUsage "$0"; } >&2; exit 2;;
*) break;;
esac
done
if [ $# -ne 0 ]; then
printUsage "$0" >&2
exit 2
fi
deleteLocalBranch()
{
local localBranch="${1:?}"; shift
git branch $branchDeleteOption "$localBranch"
}
deleteRemoteBranches()
{
git-remote-mutate "$remote" --message 'Delete branch(es)' --arguments "${@#${remote}/}" \; "${gitRemoteMutateArgs[@]}" \
push "$remote" --delete "${@#${remote}/}"
}
dryRun()
{
printf 'Prune %s\n' "$@"
}
readarray -t remoteBranches < <(git-rbr "$remote")
readarray -t localBranches < <(git-br)
if [ "$isReverse" ]; then
typeset -a oldRemoteBranches=()
for remoteBranch in "${remoteBranches[@]}"
do
contains "${remoteBranch#${remote}/}" "${localBranches[@]}" || \
oldRemoteBranches+=("$remoteBranch")
done
if [ ${#oldRemoteBranches[@]} -eq 0 ]; then
exit 99
else
${action:-deleteRemoteBranches} "${oldRemoteBranches[@]}"
fi
else
status=
for localBranch in "${localBranches[@]}"
do
trackedRemote="$(git config "branch.${localBranch}.remote" 2>/dev/null)"
if [ "$trackedRemote" = "$remote" ]; then
trackedBranch="$(git config "branch.${localBranch}.merge")"
if ! contains "${remote}/${trackedBranch##refs/heads/}" "${remoteBranches[@]}"; then
${action:-deleteLocalBranch} "$localBranch" && : ${status:=0} || status=$?
fi
fi
done
exit ${status:-99}
fi