← retour aux snippets

git: nettoyer les branches locales mergées

Lister et supprimer proprement les branches locales déjà mergées (protège main/master/develop) et purger les suivis distants obsolètes.

objectif

Éviter l’accumulation de branches locales obsolètes: détecter celles déjà mergées dans la branche de base, les supprimer en sécurité (dry-run puis exécution), et nettoyer les références distantes périmées pour vos dépôts.

code minimal

# dry-run: lister les branches locales mergées dans la branche de base
git fetch --prune
BASE="$(git symbolic-ref --quiet --short refs/remotes/origin/HEAD 2>/dev/null | sed 's@^origin/@@' || echo main)"
git branch --merged "origin/$BASE" \
  | egrep -v "^\*|^${BASE}\$|^main$|^master$|^develop$"

# suppression (après vérification)
git branch --merged "origin/$BASE" \
  | egrep -v "^\*|^${BASE}\$|^main$|^master$|^develop$" \
  | xargs -r -n1 git branch -d

utilisation

# 1) dépôt data.pm: liste puis suppression
cd ~/code/data.pm
git fetch --prune
BASE="$(git symbolic-ref --quiet --short refs/remotes/origin/HEAD 2>/dev/null | sed 's@^origin/@@' || echo main)"

git branch --merged "origin/$BASE" \
  | egrep -v "^\*|^${BASE}\$|^main$|^master$|^develop$"

git branch --merged "origin/$BASE" \
  | egrep -v "^\*|^${BASE}\$|^main$|^master$|^develop$" \
  | xargs -r -n1 git branch -d
# 2) dépôt api.data.pm: purger les suivis distants obsolètes
cd ~/code/api.data.pm
git fetch --prune
git branch -vv | awk '/: gone]/{print $1}' | xargs -r -n1 git branch -D
# 3) sécurité avant suppression manuelle d'une branche non listée comme mergée
BASE="$(git symbolic-ref --quiet --short refs/remotes/origin/HEAD 2>/dev/null | sed 's@^origin/@@' || echo main)"
curr="$(git rev-parse --abbrev-ref HEAD)"
git log --oneline --graph --decorate --boundary "origin/$BASE..$curr"

variante(s) utile(s)

# A) supprimer aussi des branches distantes mergées (avec droits)
git fetch --prune
git branch -r --merged "origin/$BASE" \
  | sed 's@^\s*origin/@@' \
  | egrep -v "^${BASE}$|^main$|^master$|^develop$" \
  | xargs -r -n1 -I{} git push origin --delete {}

# B) nettoyage rapide multi-dépôts
for repo in ~/code/data.pm ~/code/api.data.pm; do
  ( cd "$repo"
    git fetch --prune
    BASE="$(git symbolic-ref --quiet --short refs/remotes/origin/HEAD 2>/dev/null | sed 's@^origin/@@' || echo main)"
    git branch --merged "origin/$BASE" \
      | egrep -v "^\*|^${BASE}\$|^main$|^master$|^develop$" \
      | xargs -r -n1 git branch -d
  )
done

# C) script utilitaire (~/bin/git-clean-merged)
cat > ~/bin/git-clean-merged <<'SH'
#!/usr/bin/env bash
set -Eeuo pipefail
git fetch --prune
BASE="$(git symbolic-ref --quiet --short refs/remotes/origin/HEAD 2>/dev/null | sed 's@^origin/@@' || echo main)"
list="$(git branch --merged "origin/$BASE" | egrep -v "^\*|^${BASE}\$|^main$|^master$|^develop$" || true)"
[ -z "$list" ] && exit 0
echo "$list" | xargs -r -n1 git branch -d
SH
chmod +x ~/bin/git-clean-merged

# D) localiser les branches en avance (à NE PAS supprimer)
BASE="${BASE:-main}"
for b in $(git for-each-ref --format='%(refname:short)' refs/heads/); do
  ahead=$(git rev-list --left-right --count "origin/$BASE...$b" 2>/dev/null | awk '{print $2}')
  [ "${ahead:-0}" -gt 0 ] && printf "%s ahead=%s\n" "$b" "$ahead"
done

notes

  • Travaillez à jour (git fetch --prune) et basez-vous sur origin/HEAD pour détecter automatiquement main ou master.
  • Protégez les branches pivots (main, master, develop) et la branche de base détectée.
  • git branch -d échoue si la branche n’est pas mergée; utilisez -D uniquement en connaissance de cause.
  • Pour la suppression distante, validez la politique d’équipe avant d’exécuter le push --delete.