added gprune --deep parameter to allow deletion of forge merge
This commit is contained in:
@@ -497,11 +497,20 @@ export -f gwip
|
|||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Delete merged local branches (except protected branches)
|
# Delete merged local branches (except protected branches)
|
||||||
# Usage: gprune [main-branch]
|
# Usage: gprune [-D|--deep] [main-branch]
|
||||||
|
#
|
||||||
|
# Default mode: deletes branches already merged into <main-branch> locally
|
||||||
|
# (git branch --merged).
|
||||||
|
# Deep mode (-D/--deep): additionally deletes branches whose tracking remote
|
||||||
|
# has disappeared (remote pruned after a merge request / pull request merge).
|
||||||
|
# Those branches are detected via `git fetch --prune` + remote-tracking gone.
|
||||||
|
# This is the common case when the MR was merged upstream and the remote
|
||||||
|
# branch was deleted by the forge. Deletion uses `git branch -D` (force)
|
||||||
|
# because the local branch has no merged ancestor that git can verify locally.
|
||||||
gprune()
|
gprune()
|
||||||
{
|
{
|
||||||
local PARSED
|
local PARSED deep=0
|
||||||
PARSED=$(getopt -o h --long help -n 'gprune' -- "$@")
|
PARSED=$(getopt -o hD --long help,deep -n 'gprune' -- "$@")
|
||||||
# shellcheck disable=SC2181 # getopt return code is checked immediately after
|
# shellcheck disable=SC2181 # getopt return code is checked immediately after
|
||||||
if [[ $? -ne 0 ]]; then
|
if [[ $? -ne 0 ]]; then
|
||||||
disp E "Invalid options, use \"gprune --help\" to display usage."
|
disp E "Invalid options, use \"gprune --help\" to display usage."
|
||||||
@@ -512,10 +521,20 @@ gprune()
|
|||||||
while true; do
|
while true; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
-h|--help)
|
-h|--help)
|
||||||
printf "gprune: Delete local branches already merged into main branch.\n"
|
printf "gprune: Delete local branches already merged into main branch.\n\n"
|
||||||
printf "Usage: gprune [main-branch]\n"
|
printf "Usage: gprune [-D|--deep] [main-branch]\n\n"
|
||||||
|
printf "Options:\n"
|
||||||
|
printf "\t-D, --deep\tAlso delete branches whose upstream was removed\n"
|
||||||
|
printf "\t\t\t(remote deleted after MR/PR merge). Uses 'git branch -D'.\n"
|
||||||
|
printf "\t-h, --help\tDisplay this help screen\n\n"
|
||||||
|
printf "Arguments:\n"
|
||||||
|
printf "\tmain-branch\tBase branch to check merges against (default: auto-detected)\n"
|
||||||
return 0
|
return 0
|
||||||
;;
|
;;
|
||||||
|
-D|--deep)
|
||||||
|
deep=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
--)
|
--)
|
||||||
shift
|
shift
|
||||||
break
|
break
|
||||||
@@ -532,6 +551,7 @@ gprune()
|
|||||||
local base="${1:-$(_git_default_branch "$GIT_DEFAULT_REMOTE")}" current deleted=0
|
local base="${1:-$(_git_default_branch "$GIT_DEFAULT_REMOTE")}" current deleted=0
|
||||||
current=$(git rev-parse --abbrev-ref HEAD 2>/dev/null) || return 1
|
current=$(git rev-parse --abbrev-ref HEAD 2>/dev/null) || return 1
|
||||||
|
|
||||||
|
# ── Standard mode: branches locally merged into base ──────────────────────
|
||||||
disp I "Pruning branches merged into $base..."
|
disp I "Pruning branches merged into $base..."
|
||||||
|
|
||||||
while IFS= read -r b; do
|
while IFS= read -r b; do
|
||||||
@@ -540,12 +560,35 @@ gprune()
|
|||||||
[[ $b == "$base" ]] && continue
|
[[ $b == "$base" ]] && continue
|
||||||
[[ $b == "master" || $b == "main" || $b == "develop" || $b == "dev" ]] && continue
|
[[ $b == "master" || $b == "main" || $b == "develop" || $b == "dev" ]] && continue
|
||||||
git branch -d "$b" >/dev/null 2>&1 && {
|
git branch -d "$b" >/dev/null 2>&1 && {
|
||||||
printf "Deleted: %s\n" "$b"
|
printf "Deleted (merged): %s\n" "$b"
|
||||||
((deleted++))
|
((deleted++))
|
||||||
}
|
}
|
||||||
done < <(git branch --merged "$base" | sed -E 's/^\*?\s*//')
|
done < <(git branch --merged "$base" | sed -E 's/^\*?\s*//')
|
||||||
|
|
||||||
(( deleted == 0 )) && disp I "No merged branches to delete."
|
# ── Deep mode: branches whose remote tracking ref was deleted upstream ─────
|
||||||
|
if (( deep )); then
|
||||||
|
disp I "Deep mode: pruning remote-tracking refs, then checking for gone branches..."
|
||||||
|
git fetch --prune --quiet
|
||||||
|
|
||||||
|
while IFS= read -r b; do
|
||||||
|
[[ -z $b ]] && continue
|
||||||
|
[[ $b == "$current" ]] && continue
|
||||||
|
[[ $b == "$base" ]] && continue
|
||||||
|
[[ $b == "master" || $b == "main" || $b == "develop" || $b == "dev" ]] && continue
|
||||||
|
# Verify the upstream is truly gone (not just unset).
|
||||||
|
local upstream
|
||||||
|
upstream=$(git rev-parse --abbrev-ref "${b}@{upstream}" 2>/dev/null)
|
||||||
|
[[ -z "$upstream" ]] && continue # no tracking branch at all — skip
|
||||||
|
# If the remote ref still exists, skip (not deleted upstream).
|
||||||
|
git show-ref --verify --quiet "refs/remotes/$upstream" 2>/dev/null && continue
|
||||||
|
git branch -D "$b" >/dev/null 2>&1 && {
|
||||||
|
printf "Deleted (gone upstream): %s\n" "$b"
|
||||||
|
((deleted++))
|
||||||
|
}
|
||||||
|
done < <(git branch -vv | sed -E 's/^\*?\s*//' | awk '/: gone]/ {print $1}')
|
||||||
|
fi
|
||||||
|
|
||||||
|
(( deleted == 0 )) && disp I "No branches to delete."
|
||||||
}
|
}
|
||||||
export -f gprune
|
export -f gprune
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ help()
|
|||||||
printf "gacp\t\tAdd, commit and push changes (auto-pull if needed)\n"
|
printf "gacp\t\tAdd, commit and push changes (auto-pull if needed)\n"
|
||||||
printf "genpwd\t\tGenerate one or more random secure passwords with configurable constraints\n"
|
printf "genpwd\t\tGenerate one or more random secure passwords with configurable constraints\n"
|
||||||
printf "ggraph\t\tDisplay decorated git history graph\n"
|
printf "ggraph\t\tDisplay decorated git history graph\n"
|
||||||
printf "gprune\t\tDelete local branches already merged into main branch\n"
|
printf "gprune\t\tDelete local branches already merged, or after remote deletion (MR / PR)\n"
|
||||||
printf "greset\t\tReset branch to upstream (stash local, drop local commits)\n"
|
printf "greset\t\tReset branch to upstream (stash local, drop local commits)\n"
|
||||||
printf "groot\t\tDisplay repository root path (or cd to it with -g)\n"
|
printf "groot\t\tDisplay repository root path (or cd to it with -g)\n"
|
||||||
printf "gsync\t\tFetch and rebase current branch onto upstream\n"
|
printf "gsync\t\tFetch and rebase current branch onto upstream\n"
|
||||||
|
|||||||
Reference in New Issue
Block a user