1
+ #! /bin/bash
2
+
3
+ # ##############################################################################
4
+ # Git Branch Cleanup Script
5
+ #
6
+ # This script safely removes all local and remote branches except master and main.
7
+ # It includes safety checks, error handling, and detailed logging of operations.
8
+ #
9
+ # Usage:
10
+ # ./git-cleanup.sh
11
+ #
12
+ # Requirements:
13
+ # - Git must be installed
14
+ # - Script must be run from within a git repository
15
+ # - User must have appropriate permissions for branch deletion
16
+ #
17
+ # Safety Features:
18
+ # - Preserves master and main branches
19
+ # - Checks for uncommitted changes
20
+ # - Requires confirmation before deletion
21
+ # - Validates git repository status
22
+ # - Handles network and command failures
23
+ # ##############################################################################
24
+
25
+ # Exit on any error, but ensure we handle the error appropriately
26
+ set -eE
27
+
28
+ # Text colors for output
29
+ RED=' \033[0;31m'
30
+ GREEN=' \033[0;32m'
31
+ YELLOW=' \033[1;33m'
32
+ NC=' \033[0m' # No Color
33
+
34
+ # Error handler function
35
+ handle_error () {
36
+ local line_number=$1
37
+ local error_code=$2
38
+ print_message " $RED " " Error occurred in line ${line_number} (Exit code: ${error_code} )"
39
+ case ${error_code} in
40
+ 128)
41
+ print_message " $RED " " Git repository error: Command failed due to repository state"
42
+ ;;
43
+ 1)
44
+ print_message " $RED " " General error: Command failed to execute properly"
45
+ ;;
46
+ * )
47
+ print_message " $RED " " Unknown error occurred"
48
+ ;;
49
+ esac
50
+ exit ${error_code}
51
+ }
52
+
53
+ # Set up error trap
54
+ trap ' handle_error ${LINENO} $?' ERR
55
+
56
+ # ##############################################################################
57
+ # Utility Functions
58
+ # ##############################################################################
59
+
60
+ # Function: print_message
61
+ # Description: Prints a colored message to stdout
62
+ # Parameters:
63
+ # $1 - Color code
64
+ # $2 - Message to print
65
+ print_message () {
66
+ local color=$1
67
+ local message=$2
68
+ echo -e " ${color}${message}${NC} "
69
+ }
70
+
71
+ # Function: check_git_repo
72
+ # Description: Validates that the current directory is a git repository
73
+ # Exits with error if not in a git repository
74
+ check_git_repo () {
75
+ print_message " $YELLOW " " Checking repository status..."
76
+ if ! git rev-parse --is-inside-work-tree > /dev/null 2>&1 ; then
77
+ print_message " $RED " " Error: Not a git repository"
78
+ print_message " $YELLOW " " Please run this script from within a git repository"
79
+ exit 1
80
+ fi
81
+ }
82
+
83
+ # Function: check_git_installed
84
+ # Description: Verifies that git is installed and accessible
85
+ check_git_installed () {
86
+ if ! command -v git > /dev/null 2>&1 ; then
87
+ print_message " $RED " " Error: Git is not installed"
88
+ print_message " $YELLOW " " Please install git before running this script"
89
+ exit 1
90
+ fi
91
+ }
92
+
93
+ # Function: check_working_directory
94
+ # Description: Ensures the working directory is clean before proceeding
95
+ check_working_directory () {
96
+ local has_changes=0
97
+
98
+ # Check for staged changes
99
+ if ! git diff --staged --quiet; then
100
+ print_message " $RED " " Error: You have staged changes"
101
+ has_changes=1
102
+ fi
103
+
104
+ # Check for unstaged changes
105
+ if ! git diff --quiet; then
106
+ print_message " $RED " " Error: You have unstaged changes"
107
+ has_changes=1
108
+ fi
109
+
110
+ # Check for untracked files
111
+ if [ -n " $( git ls-files --others --exclude-standard) " ]; then
112
+ print_message " $RED " " Error: You have untracked files"
113
+ has_changes=1
114
+ fi
115
+
116
+ if [ $has_changes -eq 1 ]; then
117
+ print_message " $YELLOW " " Please commit or stash your changes before proceeding"
118
+ exit 1
119
+ fi
120
+ }
121
+
122
+ # Function: fetch_latest
123
+ # Description: Fetches the latest changes from all remotes and prunes deleted branches
124
+ # Handles network errors and remote connectivity issues
125
+ fetch_latest () {
126
+ print_message " $YELLOW " " Fetching latest changes from remote..."
127
+ if ! git fetch --all --prune; then
128
+ print_message " $RED " " Error: Failed to fetch from remote"
129
+ print_message " $YELLOW " " Please check your internet connection and remote repository access"
130
+ exit 1
131
+ fi
132
+ }
133
+
134
+ # ##############################################################################
135
+ # Main Cleanup Function
136
+ # ##############################################################################
137
+
138
+ # Function: cleanup_branches
139
+ # Description: Performs the main branch cleanup operation
140
+ # - Switches to main/master branch
141
+ # - Deletes local branches
142
+ # - Deletes remote branches
143
+ # - Performs garbage collection
144
+ cleanup_branches () {
145
+ local current_branch=$( git branch --show-current)
146
+ local default_branch=" "
147
+
148
+ # Determine and switch to default branch
149
+ if git show-ref --verify --quiet refs/heads/main; then
150
+ default_branch=" main"
151
+ elif git show-ref --verify --quiet refs/heads/master; then
152
+ default_branch=" master"
153
+ else
154
+ print_message " $RED " " Error: Neither main nor master branch found"
155
+ print_message " $YELLOW " " Please create either a main or master branch first"
156
+ exit 1
157
+ fi
158
+
159
+ print_message " $YELLOW " " Switching to ${default_branch} branch..."
160
+ if ! git checkout " $default_branch " ; then
161
+ print_message " $RED " " Error: Failed to switch to ${default_branch} branch"
162
+ exit 1
163
+ fi
164
+
165
+ # Delete local branches
166
+ print_message " $YELLOW " " Deleting local branches..."
167
+ local local_branches=$( git branch | grep -v " main\|master\|\*" || true)
168
+ if [ -n " $local_branches " ]; then
169
+ echo " $local_branches " | xargs -r git branch -D
170
+ else
171
+ print_message " $GREEN " " No local branches to delete"
172
+ fi
173
+
174
+ # Delete remote branches
175
+ print_message " $YELLOW " " Deleting remote branches..."
176
+ local remote_branches=$( git branch -r | grep -v " main\|master" | sed ' s/origin\///' || true)
177
+ if [ -n " $remote_branches " ]; then
178
+ echo " $remote_branches " | xargs -r -I {} git push origin --delete {}
179
+ else
180
+ print_message " $GREEN " " No remote branches to delete"
181
+ fi
182
+
183
+ # Clean up references and optimize repository
184
+ print_message " $YELLOW " " Performing repository cleanup..."
185
+ git gc --prune=now
186
+
187
+ # Return to original branch if it still exists
188
+ if [ " $current_branch " != " $default_branch " ] && \
189
+ git show-ref --verify --quiet refs/heads/" $current_branch " ; then
190
+ print_message " $YELLOW " " Returning to original branch: ${current_branch} "
191
+ git checkout " $current_branch "
192
+ fi
193
+ }
194
+
195
+ # ##############################################################################
196
+ # Main Script Execution
197
+ # ##############################################################################
198
+
199
+ main () {
200
+ print_message " $YELLOW " " Starting Git branch cleanup..."
201
+
202
+ # Initial checks
203
+ check_git_installed
204
+ check_git_repo
205
+ check_working_directory
206
+ fetch_latest
207
+
208
+ # Prompt for confirmation
209
+ print_message " $YELLOW " " WARNING: This will delete all branches except main and master."
210
+ print_message " $YELLOW " " This operation cannot be undone!"
211
+ read -p " Do you want to continue? (y/N) " -n 1 -r
212
+ echo
213
+ if [[ ! $REPLY =~ ^[Yy]$ ]]; then
214
+ print_message " $YELLOW " " Operation cancelled by user"
215
+ exit 0
216
+ fi
217
+
218
+ # Perform cleanup
219
+ cleanup_branches
220
+
221
+ print_message " $GREEN " " Branch cleanup completed successfully!"
222
+ print_message " $GREEN " " Your repository is now clean!"
223
+ }
224
+
225
+ # Execute main function
226
+ main " $@ "
0 commit comments