gitbash 0.1.0

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.
@@ -0,0 +1,211 @@
1
+ #!/usr/bin/env bash
2
+ # shellcheck disable=SC2155
3
+
4
+ # List recent commits and optionally revert selected ones
5
+ commits() {
6
+ # -----------------------------
7
+ # 0. Check for help flag
8
+ # -----------------------------
9
+ if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
10
+ cat << 'EOF'
11
+ Usage: commits [COUNT]
12
+
13
+ List recent commits in the current branch with option to revert selected ones.
14
+
15
+ Arguments:
16
+ COUNT Number of commits to show (default: 20)
17
+
18
+ Navigation:
19
+ ↑/↓ or j/k Navigate through commits
20
+ TAB Select/deselect commit for revert
21
+ Enter Revert selected commit(s)
22
+ ESC/Ctrl-C Exit without action
23
+
24
+ Notes:
25
+ - Shows commits from newest to oldest
26
+ - Preview shows full commit diff
27
+ - Multiple commits can be selected for revert
28
+ - Reverts are done in reverse order (oldest first) to avoid conflicts
29
+ - Each revert creates a new commit
30
+
31
+ Examples:
32
+ $ commits
33
+ # Shows last 20 commits
34
+
35
+ $ commits 50
36
+ # Shows last 50 commits
37
+
38
+ Requirements:
39
+ - Must be in a git repository
40
+ - fzf (fuzzy finder)
41
+
42
+ EOF
43
+ return 0
44
+ fi
45
+
46
+ # -----------------------------
47
+ # 1. Check prerequisites
48
+ # -----------------------------
49
+ if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
50
+ echo "Not inside a git repository."
51
+ return 1
52
+ fi
53
+
54
+ if ! command -v fzf >/dev/null 2>&1; then
55
+ echo "fzf is not installed."
56
+ read -rp "Install fzf with Homebrew? (y/N): " ans
57
+ case "$ans" in
58
+ [yY][eE][sS]|[yY])
59
+ echo "Installing fzf with brew..."
60
+ if ! command -v brew >/dev/null 2>&1; then
61
+ echo "Homebrew is not installed. Aborting."
62
+ return 1
63
+ fi
64
+ brew install fzf || { echo "fzf install failed. Aborting."; return 1; }
65
+ ;;
66
+ *)
67
+ echo "Aborted (skipped fzf installation)."
68
+ return 1
69
+ ;;
70
+ esac
71
+ fi
72
+
73
+ # -----------------------------
74
+ # 2. Get commit count
75
+ # -----------------------------
76
+ local count="${1:-20}"
77
+ local abort_label="✖ Abort"
78
+ local current_branch
79
+ current_branch=$(git rev-parse --abbrev-ref HEAD)
80
+
81
+ # -----------------------------
82
+ # 3. Build commit list
83
+ # -----------------------------
84
+ local commit_list
85
+ commit_list=$(git log -n "$count" --format="%h|%s|%cr|%an" | while IFS='|' read -r hash subject date author; do
86
+ # Truncate subject if too long
87
+ if [[ ${#subject} -gt 60 ]]; then
88
+ subject="${subject:0:57}..."
89
+ fi
90
+ printf "%-8s %-60s %-15s %s\t%s\n" "$hash" "$subject" "$date" "$author" "$hash"
91
+ done)
92
+
93
+ if [[ -z "$commit_list" ]]; then
94
+ echo "No commits found."
95
+ return 0
96
+ fi
97
+
98
+ # Add abort option
99
+ commit_list+=$'\n'"$abort_label"$'\t'
100
+
101
+ # Create temp file
102
+ local commit_file
103
+ commit_file=$(mktemp)
104
+ echo "$commit_list" > "$commit_file"
105
+
106
+ # -----------------------------
107
+ # 4. Run fzf picker
108
+ # -----------------------------
109
+ local selection
110
+ selection=$(cat "$commit_file" | fzf \
111
+ --prompt="Commits on '$current_branch' > " \
112
+ -i \
113
+ --reverse \
114
+ --border \
115
+ --header="[TAB] select for revert | [Enter] revert selected | [ESC] exit
116
+ Showing last $count commits" \
117
+ --multi \
118
+ --delimiter=$'\t' \
119
+ --with-nth=1 \
120
+ --bind=enter:accept \
121
+ --preview='
122
+ line={}
123
+ if [[ "$line" == "✖ Abort"* ]]; then
124
+ echo "Exit without action";
125
+ else
126
+ hash=$(echo "$line" | cut -f2)
127
+ echo "Commit: $hash";
128
+ echo "";
129
+ git show --stat --color=always "$hash" 2>/dev/null;
130
+ echo "";
131
+ echo "─────────────────────────────────────────────────────";
132
+ echo "";
133
+ git show --color=always "$hash" 2>/dev/null | head -100;
134
+ fi
135
+ ' \
136
+ --preview-window=right:50%
137
+ )
138
+
139
+ # Cleanup temp file
140
+ rm -f "$commit_file"
141
+
142
+ # ESC or Ctrl-C
143
+ if [[ -z "$selection" ]]; then
144
+ echo "Exited."
145
+ return 0
146
+ fi
147
+
148
+ # Abort option
149
+ if echo "$selection" | grep -q "^$abort_label"; then
150
+ echo "Aborted."
151
+ return 0
152
+ fi
153
+
154
+ # -----------------------------
155
+ # 5. Extract commit hashes and confirm revert
156
+ # -----------------------------
157
+ local commits_to_revert=()
158
+
159
+ while IFS= read -r line; do
160
+ [[ "$line" == "✖ Abort"* ]] && continue
161
+ local hash
162
+ hash=$(echo "$line" | cut -f2)
163
+ if [[ -n "$hash" ]]; then
164
+ commits_to_revert+=("$hash")
165
+ fi
166
+ done <<< "$selection"
167
+
168
+ if [[ ${#commits_to_revert[@]} -eq 0 ]]; then
169
+ echo "No commits selected."
170
+ return 0
171
+ fi
172
+
173
+ echo ""
174
+ echo "Selected commits to revert:"
175
+ for hash in "${commits_to_revert[@]}"; do
176
+ local subject
177
+ subject=$(git log -1 --format="%s" "$hash")
178
+ echo " - $hash: $subject"
179
+ done
180
+ echo ""
181
+
182
+ local confirm
183
+ read -rp "Revert these ${#commits_to_revert[@]} commit(s)? (y/N): " confirm
184
+ case "$confirm" in
185
+ [yY][eE][sS]|[yY])
186
+ echo "Reverting commits..."
187
+
188
+ # Reverse the array to revert oldest first (avoids conflicts)
189
+ local reversed=()
190
+ for ((i=${#commits_to_revert[@]}-1; i>=0; i--)); do
191
+ reversed+=("${commits_to_revert[$i]}")
192
+ done
193
+
194
+ for hash in "${reversed[@]}"; do
195
+ echo "Reverting $hash ..."
196
+ if git revert --no-edit "$hash"; then
197
+ echo "✓ Reverted $hash"
198
+ else
199
+ echo "✗ Failed to revert $hash (conflict?)"
200
+ echo " Resolve the conflict and run 'git revert --continue'"
201
+ return 1
202
+ fi
203
+ done
204
+ echo ""
205
+ echo "✓ All selected commits reverted."
206
+ ;;
207
+ *)
208
+ echo "Revert cancelled."
209
+ ;;
210
+ esac
211
+ }
@@ -0,0 +1,205 @@
1
+ #!/usr/bin/env bash
2
+ # shellcheck disable=SC2155
3
+
4
+ create() {
5
+ # -----------------------------
6
+ # 0. Check for help flag
7
+ # -----------------------------
8
+ if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
9
+ cat << 'EOF'
10
+ Usage: create [JIRA_LINK] [TITLE...]
11
+
12
+ Create a new git branch with the pattern: feature/<ISSUE>-<title>
13
+
14
+ Options:
15
+ -h, --help Show this help message
16
+
17
+ Configuration:
18
+ - Branch prefix can be changed by editing the 'GITBASH_FEATURE_BRANCH_PREFIX' variable
19
+ - Default: "feature/"
20
+
21
+ Interactive mode (no arguments):
22
+ $ create
23
+ Enter Jira link (e.g., https://jira.company.com/browse/PROJ-123):
24
+ > https://jira.company.com/browse/PROJ-123
25
+ Parsed issue number: PROJ-123
26
+
27
+ Enter branch title (will be converted to lowercase with dashes):
28
+ > Fix Login Bug
29
+
30
+ Branch name: feature/PROJ-123-fix-login-bug
31
+ Create this branch? (y/N): y
32
+
33
+ One-liner mode (with arguments):
34
+ $ create https://jira.company.com/browse/PROJ-123 fix login bug
35
+ Parsed issue number: PROJ-123
36
+
37
+ Branch name: feature/PROJ-123-fix-login-bug
38
+ Create this branch? (y/N): y
39
+
40
+ $ create PROJ-456 add user settings
41
+ Parsed issue number: PROJ-456
42
+
43
+ Branch name: feature/PROJ-456-add-user-settings
44
+ Create this branch? (y/N): y
45
+
46
+ Examples:
47
+ create https://jira.company.com/browse/PROJ-123 make some fixes
48
+ create PROJ-456 implement new feature
49
+ create https://company.atlassian.net/browse/ABC-789 refactor code
50
+
51
+ EOF
52
+ return 0
53
+ fi
54
+
55
+ # -----------------------------
56
+ # 1. Get Jira link from user (or from arguments)
57
+ # -----------------------------
58
+ local jira_link
59
+ local branch_title
60
+
61
+ if [[ -n "${1:-}" ]]; then
62
+ # Arguments provided - use one-liner mode
63
+ jira_link="$1"
64
+ shift
65
+ # Join remaining arguments as title
66
+ branch_title="$*"
67
+ else
68
+ # Interactive mode
69
+ echo "Enter Jira link (e.g., https://jira.company.com/browse/PROJ-123):"
70
+ read -rp " > " jira_link
71
+ fi
72
+
73
+ if [[ -z "$jira_link" ]]; then
74
+ echo "Error: No Jira link provided."
75
+ return 1
76
+ fi
77
+
78
+ # -----------------------------
79
+ # 2. Parse issue number from Jira link
80
+ # -----------------------------
81
+ local issue_number
82
+ # First try to match just the issue number pattern (e.g., PROJ-123)
83
+ issue_number=$(echo "$jira_link" | grep -o -E '^[A-Z]+-[0-9]+$' | head -1)
84
+
85
+ # If not a direct match, try to extract from URL
86
+ if [[ -z "$issue_number" ]]; then
87
+ # Match patterns like PROJ-123, ABC-456, etc.
88
+ # Supports both /browse/PROJ-123 and selectedIssue=PROJ-123 formats
89
+ issue_number=$(echo "$jira_link" | grep -o -E '(browse/|selectedIssue=)[A-Z]+-[0-9]+' | grep -o '[A-Z]\+-[0-9]\+' | head -1)
90
+ fi
91
+
92
+ if [[ -z "$issue_number" ]]; then
93
+ echo "Warning: Could not parse issue number from Jira link. Using NOISSUE."
94
+ issue_number="NOISSUE"
95
+ # If parsing failed and we had arguments, include the first arg in the title
96
+ if [[ -n "$branch_title" ]]; then
97
+ branch_title="$jira_link $branch_title"
98
+ else
99
+ branch_title="$jira_link"
100
+ fi
101
+ else
102
+ echo "Parsed issue number: $issue_number"
103
+ fi
104
+ echo
105
+
106
+ # -----------------------------
107
+ # 3. Get branch title from user (if not already provided)
108
+ # -----------------------------
109
+ if [[ -z "$branch_title" ]]; then
110
+ echo "Enter branch title (will be converted to lowercase with dashes):"
111
+ read -rp " > " branch_title
112
+ fi
113
+
114
+ if [[ -z "$branch_title" ]]; then
115
+ echo "Error: No branch title provided."
116
+ return 1
117
+ fi
118
+
119
+ # Convert title to lowercase and replace spaces/special chars with dashes
120
+ branch_title=$(echo "$branch_title" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g' | sed 's/^-//;s/-$//')
121
+
122
+ # -----------------------------
123
+ # 4. Construct branch name
124
+ # -----------------------------
125
+ local branch_prefix="${GITBASH_FEATURE_BRANCH_PREFIX:-feature/}"
126
+ local branch_name="${branch_prefix}${issue_number}-${branch_title}"
127
+
128
+ echo
129
+ echo "Branch name: $branch_name"
130
+ echo
131
+
132
+ # -----------------------------
133
+ # 5. Check if branch already exists
134
+ # -----------------------------
135
+ if git show-ref --verify --quiet "refs/heads/$branch_name"; then
136
+ echo "⚠ Branch '$branch_name' already exists locally."
137
+ read -rp "Switch to this branch instead? (Y/n): " ans
138
+ case "$ans" in
139
+ [nN][oO]|[nN])
140
+ echo "Aborted."
141
+ return 1
142
+ ;;
143
+ *)
144
+ git checkout "$branch_name"
145
+ echo "✓ Switched to existing branch: $branch_name"
146
+ return 0
147
+ ;;
148
+ esac
149
+ fi
150
+
151
+ # -----------------------------
152
+ # 6. Update main/master branch before creating new branch
153
+ # -----------------------------
154
+ # Detect base branch: main or master
155
+ local base_branch
156
+ if git show-ref --verify --quiet refs/heads/main; then
157
+ base_branch="main"
158
+ elif git show-ref --verify --quiet refs/heads/master; then
159
+ base_branch="master"
160
+ else
161
+ echo "⚠ Could not detect 'main' or 'master' branch. Creating branch from current HEAD."
162
+ base_branch=""
163
+ fi
164
+
165
+ if [[ -n "$base_branch" ]]; then
166
+ echo "Updating '$base_branch' from origin..."
167
+ if git fetch origin "$base_branch:$base_branch" 2>/dev/null; then
168
+ echo "✓ '$base_branch' is up to date."
169
+ else
170
+ echo "⚠ Could not update '$base_branch' from origin. Creating branch from local '$base_branch'."
171
+ fi
172
+ fi
173
+
174
+ # -----------------------------
175
+ # 7. Create branch
176
+ # -----------------------------
177
+ echo "Creating branch..."
178
+ if [[ -n "$base_branch" ]]; then
179
+ # Create branch from updated base branch
180
+ if git checkout -b "$branch_name" "$base_branch"; then
181
+ echo "✓ Successfully created and switched to branch: $branch_name (from $base_branch)"
182
+ else
183
+ echo "✗ Failed to create branch."
184
+ return 1
185
+ fi
186
+ else
187
+ # Fallback: create from current HEAD
188
+ if git checkout -b "$branch_name"; then
189
+ echo "✓ Successfully created and switched to branch: $branch_name"
190
+ else
191
+ echo "✗ Failed to create branch."
192
+ return 1
193
+ fi
194
+ fi
195
+
196
+ # -----------------------------
197
+ # 8. Push branch to origin and set up tracking
198
+ # -----------------------------
199
+ echo "Pushing branch to origin and setting up tracking..."
200
+ if git push -u origin "$branch_name"; then
201
+ echo "✓ Successfully pushed '$branch_name' to origin with tracking."
202
+ else
203
+ echo "⚠ Failed to push branch to origin. You can push it later with: git push -u origin $branch_name"
204
+ fi
205
+ }
package/commands/pr.sh ADDED
@@ -0,0 +1,130 @@
1
+ ## pr opens the current pr, if in repo
2
+ pr() {
3
+ local should_push=false
4
+
5
+ # Parse arguments
6
+ while [[ $# -gt 0 ]]; do
7
+ case $1 in
8
+ -h|--help)
9
+ cat << 'EOF'
10
+ Usage: pr [OPTIONS]
11
+
12
+ Open the current branch's pull request in your browser.
13
+ If no PR exists, opens GitHub's compare page to create one.
14
+
15
+ Options:
16
+ -p, --push Push current branch to origin before opening PR
17
+ -h, --help Show this help message
18
+
19
+ Behavior:
20
+ - Must be run inside a git repository
21
+ - Uses the 'origin' remote URL
22
+ - Opens a compare URL for the current branch
23
+ - Automatically converts SSH URLs to HTTPS
24
+
25
+ Examples:
26
+ $ pr
27
+ # Opens: https://github.com/user/repo/compare/feature-branch?expand=1
28
+
29
+ $ git checkout feature/helix/LOVE-123-fix-bug
30
+ $ pr
31
+ # Opens: https://github.com/user/repo/compare/feature/helix/LOVE-123-fix-bug?expand=1
32
+
33
+ # Push before opening PR
34
+ $ pr -p
35
+ Pushing 'feature-branch' to origin...
36
+ ✓ Successfully pushed 'feature-branch' to origin.
37
+ # Opens: https://github.com/user/repo/compare/feature-branch?expand=1
38
+
39
+ Notes:
40
+ - Works with both SSH and HTTPS remote URLs
41
+ - Opens in your default browser using the 'open' command
42
+ - Branch name is automatically URL-encoded by the browser
43
+
44
+ EOF
45
+ return 0
46
+ ;;
47
+ -p|--push)
48
+ should_push=true
49
+ shift
50
+ ;;
51
+ -*)
52
+ echo "Unknown option: $1"
53
+ echo "Usage: pr [-p|--push]"
54
+ return 1
55
+ ;;
56
+ *)
57
+ echo "Unknown argument: $1"
58
+ echo "Usage: pr [-p|--push]"
59
+ return 1
60
+ ;;
61
+ esac
62
+ done
63
+
64
+ # Ensure we're inside a Git repo
65
+ if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
66
+ echo "Not inside a git repository."
67
+ return 1
68
+ fi
69
+
70
+ # Remote URL (e.g. git@github.com:user/repo.git or https://github.com/user/repo.git)
71
+ remote=$(git config --get remote.origin.url)
72
+
73
+ if [[ -z "$remote" ]]; then
74
+ echo "No remote 'origin' found."
75
+ return 1
76
+ fi
77
+
78
+ # Convert SSH URLs to HTTPS URLs
79
+ remote_https=$remote
80
+ remote_https=${remote_https/git@github.com:/https://github.com/}
81
+ remote_https=${remote_https%.git}
82
+
83
+ # Current branch
84
+ branch=$(git rev-parse --abbrev-ref HEAD)
85
+
86
+ # Push if requested
87
+ if [[ "$should_push" == true ]]; then
88
+ # Check if remote has updates and pull first
89
+ git fetch origin "$branch" 2>/dev/null
90
+ local local_commit=$(git rev-parse HEAD)
91
+ local remote_commit=$(git rev-parse "origin/$branch" 2>/dev/null)
92
+
93
+ if [[ -n "$remote_commit" && "$local_commit" != "$remote_commit" ]]; then
94
+ # Check if we're behind the remote
95
+ if git merge-base --is-ancestor "$local_commit" "$remote_commit" 2>/dev/null; then
96
+ echo "Remote has updates. Pulling first..."
97
+ git pull --rebase origin "$branch"
98
+ if [[ $? -ne 0 ]]; then
99
+ echo "⚠ Failed to pull remote changes. Please resolve conflicts and try again."
100
+ return 1
101
+ fi
102
+ echo "✓ Pulled latest changes."
103
+ elif ! git merge-base --is-ancestor "$remote_commit" "$local_commit" 2>/dev/null; then
104
+ # Branches have diverged
105
+ echo "Remote has diverged. Pulling with rebase..."
106
+ git pull --rebase origin "$branch"
107
+ if [[ $? -ne 0 ]]; then
108
+ echo "⚠ Failed to pull remote changes. Please resolve conflicts and try again."
109
+ return 1
110
+ fi
111
+ echo "✓ Rebased on latest changes."
112
+ fi
113
+ fi
114
+
115
+ echo "Pushing '$branch' to origin..."
116
+ git push origin "$branch"
117
+ if [[ $? -eq 0 ]]; then
118
+ echo "✓ Successfully pushed '$branch' to origin."
119
+ else
120
+ echo "⚠ Failed to push '$branch' to origin."
121
+ return 1
122
+ fi
123
+ fi
124
+
125
+ # Construct compare URL
126
+ url="$remote_https/compare/$branch?expand=1"
127
+
128
+ # Open in browser
129
+ open "$url"
130
+ }