git-jira-shortcuts 1.0.8 → 1.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/cli.js CHANGED
@@ -172,7 +172,7 @@ After init, these zsh commands are available:
172
172
  gpu/gpush Push with tracking gdel/gdelete Delete branch
173
173
  gl/glist List pending files gr/greset Reset files
174
174
  gdiff Diff vs target branch grecent Recent branches
175
- grepos Show all repo branches testJira Test Jira API
175
+ grepos Show all repo branches gclean Delete merged branches
176
176
  ghelp Show all commands
177
177
  `);
178
178
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "git-jira-shortcuts",
3
- "version": "1.0.8",
3
+ "version": "1.0.9",
4
4
  "description": "Git + Jira workflow shortcuts for zsh — interactive branch switching, auto-prefixed commits, Jira integration, and more.",
5
5
  "author": "chipallen2",
6
6
  "license": "MIT",
@@ -8,6 +8,8 @@
8
8
  # GJS_JIRA_API_TOKEN — Base64 Jira API token
9
9
  # GJS_BRANCH_WEBHOOK_URL — Optional webhook for branch name generation
10
10
  # GJS_REPOS — Optional array of repo paths for grepos
11
+ # GJS_CLEAN_PROTECTED — Optional array of branch names to never delete with gclean
12
+ # GJS_BRANCH_ALIASES — Optional array of branch aliases (e.g. "m:master" "d:develop")
11
13
 
12
14
  # Store path to this script for self-reference (used by ghelp)
13
15
  GJS_SHELL_SCRIPT_PATH="${0:A}"
@@ -129,13 +131,32 @@ _gjs_resolve_branch_input() {
129
131
  return 0
130
132
  fi
131
133
 
132
- if [[ "$raw_input" == "m" ]]; then
133
- echo "master"
134
- return 0
135
- elif [[ "$raw_input" == "d" ]]; then
136
- echo "develop"
134
+ # Check configurable aliases first, fall back to defaults
135
+ local resolved_alias=""
136
+ if [[ -n "${GJS_BRANCH_ALIASES+x}" ]]; then
137
+ for alias_entry in "${GJS_BRANCH_ALIASES[@]}"; do
138
+ local alias_key="${alias_entry%%:*}"
139
+ local alias_val="${alias_entry#*:}"
140
+ if [[ "$raw_input" == "$alias_key" ]]; then
141
+ resolved_alias="$alias_val"
142
+ break
143
+ fi
144
+ done
145
+ fi
146
+ if [[ -n "$resolved_alias" ]]; then
147
+ echo "$resolved_alias"
137
148
  return 0
138
149
  fi
150
+ # Default aliases if GJS_BRANCH_ALIASES not set
151
+ if [[ -z "${GJS_BRANCH_ALIASES+x}" ]]; then
152
+ if [[ "$raw_input" == "m" ]]; then
153
+ echo "master"
154
+ return 0
155
+ elif [[ "$raw_input" == "d" ]]; then
156
+ echo "develop"
157
+ return 0
158
+ fi
159
+ fi
139
160
 
140
161
  if ! _gjs_is_ticket_number "$raw_input"; then
141
162
  echo "$raw_input"
@@ -337,6 +358,11 @@ ghelp() { # ghelp | Show all git-jira-shortcuts commands
337
358
  gr [file] Reset a file with confirmation — picker if no file
338
359
  greset (same)
339
360
 
361
+ ── Cleanup ────────────────────────────────────────────────────
362
+ gclean Delete local branches already merged to master
363
+ Skips: recent branches, master, develop, protected
364
+ Use --dry-run to preview without deleting
365
+
340
366
  ── Utilities ──────────────────────────────────────────────────
341
367
  grepos / repos Show all repo clones and their current branch
342
368
  testJira / tj Test your Jira API connection
@@ -364,6 +390,12 @@ ghelp() { # ghelp | Show all git-jira-shortcuts commands
364
390
 
365
391
  Branch shorthand:
366
392
  m → master d → develop
393
+ Customize in ~/.git-jira-shortcuts.env:
394
+ GJS_BRANCH_ALIASES=("m:main" "d:dev" "s:staging")
395
+
396
+ gclean config:
397
+ Protect additional branches:
398
+ GJS_CLEAN_PROTECTED=("release" "hotfix" "staging")
367
399
  EOF
368
400
  }
369
401
 
@@ -918,3 +950,132 @@ testJira() { # testJira | Test Jira API connection
918
950
  return 0
919
951
  }
920
952
  alias tj='testJira' # testJira | Test Jira API connection
953
+
954
+ gclean() { # gclean [--dry-run] | Delete local branches already merged to master (skips recent)
955
+ local dry_run=0
956
+ local days_recent=7
957
+
958
+ for arg in "$@"; do
959
+ case "$arg" in
960
+ --dry-run|-n)
961
+ dry_run=1
962
+ ;;
963
+ esac
964
+ done
965
+
966
+ # Default protected branches
967
+ local -a protected=("master" "main" "develop" "development")
968
+
969
+ # Add user-configured protected branches
970
+ if [[ -n "${GJS_CLEAN_PROTECTED+x}" ]]; then
971
+ for branch in "${GJS_CLEAN_PROTECTED[@]}"; do
972
+ protected+=("$branch")
973
+ done
974
+ fi
975
+
976
+ # Also add alias targets to protected list (custom or default)
977
+ if [[ -n "${GJS_BRANCH_ALIASES+x}" ]]; then
978
+ for alias_entry in "${GJS_BRANCH_ALIASES[@]}"; do
979
+ local alias_val="${alias_entry#*:}"
980
+ protected+=("$alias_val")
981
+ done
982
+ else
983
+ # Default alias targets (m→master, d→develop) — same fallback as _gjs_resolve_branch_input
984
+ protected+=("master" "develop")
985
+ fi
986
+
987
+ # Get recent branches (worked on in last N days)
988
+ local -a recent_branches=()
989
+ while IFS= read -r entry; do
990
+ [[ -z "$entry" ]] && continue
991
+ recent_branches+=("$entry")
992
+ done < <(git for-each-ref --sort=-committerdate --format='%(refname:short)' refs/heads/ | head -10)
993
+
994
+ # Also get branches from reflog (recently checked out)
995
+ while IFS= read -r branch; do
996
+ [[ -z "$branch" ]] && continue
997
+ if [[ -z "${recent_branches[(r)$branch]}" ]]; then
998
+ recent_branches+=("$branch")
999
+ fi
1000
+ done < <(_gjs_get_recent_branches 2>/dev/null)
1001
+
1002
+ # Determine which branch to check merges against
1003
+ local merge_target=""
1004
+ for candidate in master main; do
1005
+ if git show-ref --verify --quiet "refs/remotes/origin/$candidate" 2>/dev/null; then
1006
+ merge_target="origin/$candidate"
1007
+ break
1008
+ fi
1009
+ done
1010
+
1011
+ if [[ -z "$merge_target" ]]; then
1012
+ echo "❌ Could not find master or main branch on origin."
1013
+ return 1
1014
+ fi
1015
+
1016
+ echo "🧹 Cleaning up branches merged into ${merge_target#origin/}..."
1017
+ [[ $dry_run -eq 1 ]] && echo " (dry-run mode — no branches will be deleted)"
1018
+ echo ""
1019
+
1020
+ local deleted=0
1021
+ local skipped_protected=0
1022
+ local skipped_recent=0
1023
+
1024
+ # Build grep pattern for protected branches
1025
+ local grep_pattern="^\s*\*"
1026
+ for p in "${protected[@]}"; do
1027
+ grep_pattern="$grep_pattern|^\s*$p\$"
1028
+ done
1029
+
1030
+ while IFS= read -r branch; do
1031
+ branch=$(echo "$branch" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
1032
+ [[ -z "$branch" ]] && continue
1033
+ [[ "$branch" == \** ]] && continue
1034
+
1035
+ # Skip protected branches
1036
+ local is_protected=0
1037
+ for p in "${protected[@]}"; do
1038
+ if [[ "$branch" == "$p" ]]; then
1039
+ is_protected=1
1040
+ break
1041
+ fi
1042
+ done
1043
+ if [[ $is_protected -eq 1 ]]; then
1044
+ ((skipped_protected++))
1045
+ continue
1046
+ fi
1047
+
1048
+ # Skip recently worked branches
1049
+ local is_recent=0
1050
+ for r in "${recent_branches[@]}"; do
1051
+ if [[ "$branch" == "$r" ]]; then
1052
+ is_recent=1
1053
+ break
1054
+ fi
1055
+ done
1056
+ if [[ $is_recent -eq 1 ]]; then
1057
+ ((skipped_recent++))
1058
+ [[ $dry_run -eq 1 ]] && echo " ⏭️ Skip (recent): $branch"
1059
+ continue
1060
+ fi
1061
+
1062
+ # Delete the branch
1063
+ if [[ $dry_run -eq 1 ]]; then
1064
+ echo " 🗑️ Would delete: $branch"
1065
+ else
1066
+ if git branch -d "$branch" 2>/dev/null; then
1067
+ echo " 🗑️ Deleted: $branch"
1068
+ ((deleted++))
1069
+ fi
1070
+ fi
1071
+ done < <(git branch --merged "$merge_target" 2>/dev/null)
1072
+
1073
+ echo ""
1074
+ if [[ $dry_run -eq 1 ]]; then
1075
+ echo "Dry run complete. Use 'gclean' without --dry-run to delete."
1076
+ else
1077
+ echo "✅ Deleted $deleted branch(es)."
1078
+ fi
1079
+ [[ $skipped_recent -gt 0 ]] && echo " Skipped $skipped_recent recent branch(es)."
1080
+ }
1081
+ alias gc_clean='gclean' # gclean | Alias for gclean