Created
July 10, 2023 23:12
-
-
Save ivanopcode/2b77ad2556b757619b559892de30d518 to your computer and use it in GitHub Desktop.
git-branch-cleanup shell script that deletes local branches
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/zsh | |
# --------------------------------------------------------------------------------- | |
# Script Name: git-branch-cleanup | |
# Version: 1.0.0+2023-06-11 | |
# Author: Ivan Oparin <[email protected]> | |
# | |
# License: | |
# MIT License | |
# | |
# Permission is hereby granted, free of charge, to any person obtaining a copy | |
# of this software and associated documentation files (the "Software"), to deal | |
# in the Software without restriction, including without limitation the rights | |
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
# copies of the Software, and to permit persons to whom the Software is | |
# furnished to do so, subject to the following conditions: | |
# | |
# The above copyright notice and this permission notice shall be included in all | |
# copies or substantial portions of the Software. | |
# | |
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
# SOFTWARE. | |
# --------------------------------------------------------------------------------- | |
# SCRIPT DESCRIPTION: | |
# | |
# This script is designed to clean up local Git branches. It operates | |
# within a Git repository, deleting all local branches except those specified | |
# as "protected". Currently, the script only runs from a predefined "main" | |
# branch and will exit if attempted from any other branch. In the future, | |
# this main branch and list of protected branches will be configurable via | |
# a .gitcleanup configuration file located in the root of the repository. | |
# | |
# The script first verifies if it is being run within a Git repository, and | |
# if there are any unstaged changes. If either of these conditions fails, | |
# the script displays an appropriate error message and exits. This prevents | |
# accidental execution in non-repository directories or when unstaged changes | |
# are present. | |
# | |
# Once validated, the script checks if it's being run from the specified main | |
# branch. If not, it presents an error message and terminates. | |
# | |
# Lastly, the script iterates over each local branch. If a branch is not | |
# present in the list of protected branches, the script deletes it. This | |
# operation is performed using the 'git branch -D' command. | |
# | |
# Please see the 'NOTES TO USERS AND MAINTAINERS' section below for more | |
# information on certain command usage and other nuances. | |
# NOTES TO USERS AND MAINTAINERS: | |
# | |
# This script contains safety checks to ensure it is run only within a Git | |
# repository and when there are no unstaged changes. 'git rev-parse | |
# --is-inside-work-tree' is employed to determine if the script is being | |
# executed within a Git repository. The command returns 0 (success) when | |
# inside a Git repository, and 1 (failure) otherwise. If a non-zero status | |
# is returned, an error message is displayed and the script terminates. | |
# | |
# The script also checks for unstaged changes using 'git diff-index | |
# --quiet HEAD --'. This command compares the working directory and the | |
# index (staging area) for changes. It returns 0 if no differences are | |
# detected (i.e., there are no unstaged changes), and 1 if there are | |
# unstaged changes. If there are unstaged changes, the script displays an | |
# error message and exits. These checks help maintain the integrity of the | |
# user's Git repository and ensure the script behaves as expected. | |
# TODO: | |
# | |
# Implement a .gitcleanup configuration file which should be placed at the | |
# root of the repository. The file should contain a list of protected branches, | |
# one per line. The first line of the file should be the main branch from | |
# which this script is allowed to run. Modify the script to read from this | |
# file at the start of its execution. Make sure to handle cases where the | |
# file does not exist or is incorrectly formatted. | |
# Color codes | |
ERROR='\033[1;31m' # Bold Red | |
SUCCESS='\033[1;32m' # Bold Green | |
WARNING='\033[1;33m' # Bold Yellow | |
NOCOLOR='\033[0m' # No Color | |
# Check if this is a git repository | |
git rev-parse --is-inside-work-tree > /dev/null 2>&1 | |
if [[ $? != 0 ]]; then | |
echo -e "${ERROR}❌ This script must be run inside a Git repository.${NOCOLOR}" | |
exit 1 | |
fi | |
# Check if there are unstaged changes | |
git diff-index --quiet HEAD -- | |
if [[ $? != 0 ]]; then | |
echo "${ERROR}❌ There are unstaged changes. Please commit or stash them before running this script.${NOCOLOR}" | |
exit 1 | |
fi | |
# Configurable main branch | |
main_branch="development" | |
# Array of branches to protect, including main branch | |
protected_branches=("$main_branch" "develop" "development" "master" "main") | |
# Current branch | |
current_branch=$(git rev-parse --abbrev-ref HEAD) | |
# Check if current branch is the main branch | |
if [[ "$current_branch" != "$main_branch" ]]; then | |
echo "${ERROR}❌ This script can only be run from the ${main_branch} branch!${NOCOLOR}" | |
exit 1 | |
fi | |
# Branches to be deleted | |
branches_to_delete=() | |
# Loop over each local branch | |
for branch in $(git branch | cut -c3-); do | |
if [[ ! " ${protected_branches[@]} " =~ " ${branch} " ]]; then | |
# If branch is not in protected branches, add to delete list | |
branches_to_delete+=("$branch") | |
fi | |
done | |
# Print branches to be deleted and ask for confirmation | |
echo "${WARNING}⚠️ The following branches will be deleted:${NOCOLOR}" | |
for branch in ${branches_to_delete[@]}; do | |
echo "🔘 $branch" | |
done | |
echo "${WARNING}⚠️ Are you sure you want to continue? [Y/n]${NOCOLOR}" | |
read REPLY | |
if [[ $REPLY =~ ^[Yy]$ || $REPLY == "" ]] | |
then | |
# If confirmed, delete branches | |
for branch in ${branches_to_delete[@]}; do | |
git branch -D $branch > /dev/null | |
echo "☑️ Deleted local branch $branch" | |
done | |
echo "${SUCCESS}✅ All non-protected local branches were deleted.${NOCOLOR}" | |
else | |
echo "${ERROR}❌ No appropriate confirmation. Operation cancelled.${NOCOLOR}" | |
exit 1 | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment