1- git tag -d v1.0.0
2- git push origin :refs/tags/v1.0.0
3- git tag -a v1.0.0 -m " RandomGen v1.0.0 release with fixed"
4- git push origin v1.0.0
1+ #! /bin/bash
2+
3+ # =============================================================================
4+ # REMAKETAG - Professional Git Tag Recreation Script
5+ # =============================================================================
6+ # Author: RandomGen Project
7+ # Description: Safely recreates Git tags with enhanced features and validation
8+ # Version: 2.0.0
9+ # =============================================================================
10+
11+ set -euo pipefail
12+
13+ # Color definitions
14+ readonly RED=' \033[0;31m'
15+ readonly GREEN=' \033[0;32m'
16+ readonly YELLOW=' \033[1;33m'
17+ readonly BLUE=' \033[0;34m'
18+ readonly PURPLE=' \033[0;35m'
19+ readonly CYAN=' \033[0;36m'
20+ readonly WHITE=' \033[1;37m'
21+ readonly NC=' \033[0m' # No Color
22+
23+ # Configuration
24+ readonly SCRIPT_NAME=$( basename " $0 " )
25+ readonly SCRIPT_DIR=$( cd " $( dirname " ${BASH_SOURCE[0]} " ) " && pwd)
26+ readonly LOG_FILE=" ${SCRIPT_DIR} /remaketag.log"
27+
28+ # Default values
29+ DEFAULT_TAG=" v1.0.0"
30+ DEFAULT_MESSAGE=" RandomGen v1.0.0 release with enhanced features and fixes"
31+
32+ # =============================================================================
33+ # UTILITY FUNCTIONS
34+ # =============================================================================
35+
36+ log () {
37+ local level=" $1 "
38+ shift
39+ local message=" $* "
40+ local timestamp=$( date ' +%Y-%m-%d %H:%M:%S' )
41+
42+ echo -e " ${timestamp} [${level} ] ${message} " | tee -a " $LOG_FILE "
43+ }
44+
45+ print_header () {
46+ echo -e " ${CYAN} "
47+ echo " ╔══════════════════════════════════════════════════════════════╗"
48+ echo " ║ REMAKETAG v2.0.0 ║"
49+ echo " ║ Professional Git Tag Recreation ║"
50+ echo " ╚══════════════════════════════════════════════════════════════╝"
51+ echo -e " ${NC} "
52+ }
53+
54+ print_success () {
55+ echo -e " ${GREEN} ✓ $1 ${NC} "
56+ }
57+
58+ print_warning () {
59+ echo -e " ${YELLOW} ⚠ $1 ${NC} "
60+ }
61+
62+ print_error () {
63+ echo -e " ${RED} ✗ $1 ${NC} "
64+ }
65+
66+ print_info () {
67+ echo -e " ${BLUE} ℹ $1 ${NC} "
68+ }
69+
70+ # =============================================================================
71+ # VALIDATION FUNCTIONS
72+ # =============================================================================
73+
74+ validate_git_repo () {
75+ if ! git rev-parse --is-inside-work-tree & > /dev/null; then
76+ print_error " Not in a Git repository!"
77+ exit 1
78+ fi
79+ }
80+
81+ validate_remote () {
82+ if ! git ls-remote --exit-code origin & > /dev/null; then
83+ print_error " Cannot connect to remote 'origin'!"
84+ exit 1
85+ fi
86+ }
87+
88+ validate_tag_format () {
89+ local tag=" $1 "
90+ if [[ ! " $tag " =~ ^v[0-9]+\. [0-9]+\. [0-9]+$ ]]; then
91+ print_error " Invalid tag format! Use semantic versioning (e.g., v1.2.3)"
92+ exit 1
93+ fi
94+ }
95+
96+ check_uncommitted_changes () {
97+ if ! git diff-index --quiet HEAD --; then
98+ print_warning " You have uncommitted changes!"
99+ read -p " Continue anyway? (y/N): " -n 1 -r
100+ echo
101+ if [[ ! $REPLY =~ ^[Yy]$ ]]; then
102+ exit 1
103+ fi
104+ fi
105+ }
106+
107+ # =============================================================================
108+ # CORE FUNCTIONS
109+ # =============================================================================
110+
111+ show_current_tags () {
112+ print_info " Current tags:"
113+ git tag -l | sed ' s/^/ /' || echo " No tags found"
114+ }
115+
116+ get_latest_commit_info () {
117+ local commit_hash=$( git rev-parse --short HEAD)
118+ local commit_msg=$( git log -1 --pretty=%B | head -n1)
119+ echo " Latest commit: ${commit_hash} - ${commit_msg} "
120+ }
121+
122+ delete_local_tag () {
123+ local tag=" $1 "
124+ if git tag -l | grep -q " ^${tag} $" ; then
125+ print_info " Deleting local tag: $tag "
126+ git tag -d " $tag "
127+ print_success " Local tag deleted"
128+ else
129+ print_info " Local tag $tag does not exist"
130+ fi
131+ }
132+
133+ delete_remote_tag () {
134+ local tag=" $1 "
135+ if git ls-remote --tags origin | grep -q " refs/tags/${tag} " ; then
136+ print_info " Deleting remote tag: $tag "
137+ git push origin " :refs/tags/${tag} "
138+ print_success " Remote tag deleted"
139+ else
140+ print_info " Remote tag $tag does not exist"
141+ fi
142+ }
143+
144+ create_tag () {
145+ local tag=" $1 "
146+ local message=" $2 "
147+
148+ print_info " Creating new tag: $tag "
149+ git tag -a " $tag " -m " $message "
150+ print_success " Tag created locally"
151+ }
152+
153+ push_tag () {
154+ local tag=" $1 "
155+ print_info " Pushing tag to remote: $tag "
156+ git push origin " $tag "
157+ print_success " Tag pushed to remote"
158+ }
159+
160+ show_tag_info () {
161+ local tag=" $1 "
162+ print_info " Tag details:"
163+ git show --stat " $tag " | sed ' s/^/ /'
164+ }
165+
166+ # =============================================================================
167+ # INTERACTIVE MODE
168+ # =============================================================================
169+
170+ interactive_mode () {
171+ print_header
172+
173+ echo -e " ${PURPLE} Current repository status:${NC} "
174+ echo " Repository: $( basename " $( git rev-parse --show-toplevel) " ) "
175+ echo " Branch: $( git rev-parse --abbrev-ref HEAD) "
176+ echo " $( get_latest_commit_info) "
177+ echo
178+
179+ show_current_tags
180+ echo
181+
182+ read -p " Enter tag name [${DEFAULT_TAG} ]: " tag_name
183+ tag_name=${tag_name:- $DEFAULT_TAG }
184+
185+ validate_tag_format " $tag_name "
186+
187+ read -p " Enter tag message [${DEFAULT_MESSAGE} ]: " tag_message
188+ tag_message=${tag_message:- $DEFAULT_MESSAGE }
189+
190+ echo
191+ print_info " Summary:"
192+ echo " Tag: $tag_name "
193+ echo " Message: $tag_message "
194+ echo
195+
196+ read -p " Proceed with tag recreation? (y/N): " -n 1 -r
197+ echo
198+ if [[ ! $REPLY =~ ^[Yy]$ ]]; then
199+ print_info " Operation cancelled"
200+ exit 0
201+ fi
202+
203+ recreate_tag " $tag_name " " $tag_message "
204+ }
205+
206+ # =============================================================================
207+ # MAIN FUNCTION
208+ # =============================================================================
209+
210+ recreate_tag () {
211+ local tag=" ${1:- $DEFAULT_TAG } "
212+ local message=" ${2:- $DEFAULT_MESSAGE } "
213+
214+ print_header
215+
216+ log " INFO" " Starting tag recreation for: $tag "
217+
218+ # Validation
219+ validate_git_repo
220+ validate_remote
221+ validate_tag_format " $tag "
222+ check_uncommitted_changes
223+
224+ echo
225+ print_info " Recreating tag: $tag "
226+ echo
227+
228+ # Delete existing tags
229+ delete_local_tag " $tag "
230+ delete_remote_tag " $tag "
231+
232+ echo
233+
234+ # Create and push new tag
235+ create_tag " $tag " " $message "
236+ push_tag " $tag "
237+
238+ echo
239+ print_success " Tag recreation completed successfully!"
240+ echo
241+
242+ show_tag_info " $tag "
243+
244+ log " INFO" " Tag recreation completed for: $tag "
245+ }
246+
247+ # =============================================================================
248+ # HELP FUNCTION
249+ # =============================================================================
250+
251+ show_help () {
252+ print_header
253+ cat << EOF
254+ ${WHITE} USAGE:${NC}
255+ $SCRIPT_NAME [OPTIONS] [TAG] [MESSAGE]
256+
257+ ${WHITE} DESCRIPTION:${NC}
258+ Recreates Git tags with enhanced features, validation, and safety checks.
259+
260+ ${WHITE} OPTIONS:${NC}
261+ -h, --help Show this help message
262+ -i, --interactive Interactive mode (default)
263+ -f, --force Skip confirmation prompts
264+ -v, --verbose Enable verbose logging
265+ -q, --quiet Suppress output (errors only)
266+
267+ ${WHITE} EXAMPLES:${NC}
268+ $SCRIPT_NAME # Interactive mode
269+ $SCRIPT_NAME v1.2.3 # Recreate tag v1.2.3
270+ $SCRIPT_NAME v2.0.0 "Release v2.0.0"
271+ $SCRIPT_NAME -f v1.1.0 # Force recreation
272+
273+ ${WHITE} FEATURES:${NC}
274+ ✓ Semantic version validation
275+ ✓ Remote connectivity checks
276+ ✓ Uncommitted changes warning
277+ ✓ Detailed logging
278+ ✓ Color-coded output
279+ ✓ Interactive and batch modes
280+
281+ EOF
282+ }
283+
284+ # =============================================================================
285+ # COMMAND LINE PARSING
286+ # =============================================================================
287+
288+ parse_args () {
289+ local interactive=false
290+ local force=false
291+ local verbose=false
292+ local quiet=false
293+ local tag=" "
294+ local message=" "
295+
296+ while [[ $# -gt 0 ]]; do
297+ case $1 in
298+ -h|--help)
299+ show_help
300+ exit 0
301+ ;;
302+ -i|--interactive)
303+ interactive=true
304+ shift
305+ ;;
306+ -f|--force)
307+ force=true
308+ shift
309+ ;;
310+ -v|--verbose)
311+ verbose=true
312+ shift
313+ ;;
314+ -q|--quiet)
315+ quiet=true
316+ shift
317+ ;;
318+ -* )
319+ print_error " Unknown option: $1 "
320+ show_help
321+ exit 1
322+ ;;
323+ * )
324+ if [[ -z " $tag " ]]; then
325+ tag=" $1 "
326+ elif [[ -z " $message " ]]; then
327+ message=" $1 "
328+ else
329+ print_error " Too many arguments"
330+ show_help
331+ exit 1
332+ fi
333+ shift
334+ ;;
335+ esac
336+ done
337+
338+ # Set defaults if not provided
339+ tag=${tag:- $DEFAULT_TAG }
340+ message=${message:- $DEFAULT_MESSAGE }
341+
342+ # Handle quiet mode
343+ if [[ " $quiet " == true ]]; then
344+ exec 1> /dev/null
345+ fi
346+
347+ # Handle verbose mode
348+ if [[ " $verbose " == true ]]; then
349+ set -x
350+ fi
351+
352+ # Determine mode
353+ if [[ " $interactive " == true ]] || [[ $# -eq 0 ]]; then
354+ interactive_mode
355+ else
356+ recreate_tag " $tag " " $message "
357+ fi
358+ }
359+
360+ # =============================================================================
361+ # MAIN EXECUTION
362+ # =============================================================================
363+
364+ # Initialize log file
365+ touch " $LOG_FILE " 2> /dev/null || true
366+
367+ # Trap errors
368+ trap ' print_error "Script failed at line $LINENO"' ERR
369+
370+ # Execute main function
371+ parse_args " $@ "
0 commit comments