gitbash 2.0.0 → 2.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.
- package/README.md +64 -17
- package/bin/gitbash +58 -10
- package/commands/_self_update.sh +319 -0
- package/commands/_utils.sh +117 -6
- package/commands/branch.sh +3 -3
- package/commands/cleanstash.sh +1 -1
- package/commands/cleanup.sh +4 -4
- package/commands/commit.sh +1 -1
- package/commands/commits.sh +59 -10
- package/commands/create.sh +1 -1
- package/commands/pr.sh +2 -48
- package/commands/repo.sh +82 -0
- package/commands/reset-repo.sh +200 -0
- package/commands/stale.sh +4 -4
- package/commands/stash.sh +1 -1
- package/commands/stashes.sh +2 -2
- package/commands/status.sh +3 -3
- package/commands/switch.sh +16 -25
- package/commands/unstash.sh +6 -4
- package/commands/update.sh +1 -1
- package/docs/CONTRIBUTING.md +1 -0
- package/docs/SECURITY.md +1 -1
- package/package.json +2 -2
package/commands/_utils.sh
CHANGED
|
@@ -20,6 +20,21 @@ _gb_color_ok() {
|
|
|
20
20
|
[[ -z "${NO_COLOR:-}" && -t "$1" ]]
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
# NO_COLOR (https://no-color.org): a non-empty value turns off all colors.
|
|
24
|
+
# GB_COLOR is the --color value for git and bat in fzf previews; it is
|
|
25
|
+
# exported because previews run in a separate bash started by fzf.
|
|
26
|
+
if [[ -n "${NO_COLOR:-}" ]]; then
|
|
27
|
+
GB_COLOR="never"
|
|
28
|
+
# Also for git's own output (added to any GIT_CONFIG_* entries already set)
|
|
29
|
+
_gb_n="${GIT_CONFIG_COUNT:-0}"
|
|
30
|
+
export "GIT_CONFIG_KEY_$_gb_n=color.ui" "GIT_CONFIG_VALUE_$_gb_n=never"
|
|
31
|
+
export GIT_CONFIG_COUNT=$((_gb_n + 1))
|
|
32
|
+
unset _gb_n
|
|
33
|
+
else
|
|
34
|
+
GB_COLOR="always"
|
|
35
|
+
fi
|
|
36
|
+
export GB_COLOR
|
|
37
|
+
|
|
23
38
|
_gb_print() {
|
|
24
39
|
local fd="$1" color="$2" symbol="$3"
|
|
25
40
|
shift 3
|
|
@@ -35,6 +50,26 @@ print_info() { _gb_print 1 "0;34" "ℹ" "$@"; }
|
|
|
35
50
|
print_warning() { _gb_print 2 "0;33" "⚠" "$@"; }
|
|
36
51
|
print_error() { _gb_print 2 "0;31" "✗" "$@"; }
|
|
37
52
|
|
|
53
|
+
# Print help text from stdin, coloring the section headings
|
|
54
|
+
# ("Options:", "See also:", ...) and the "Usage:" label.
|
|
55
|
+
gb_help() {
|
|
56
|
+
if ! _gb_color_ok 1; then
|
|
57
|
+
cat
|
|
58
|
+
return 0
|
|
59
|
+
fi
|
|
60
|
+
local h=$'\033[1;38;5;209m' r=$'\033[0m' line
|
|
61
|
+
local heading='^[A-Z][A-Za-z ()]*:$'
|
|
62
|
+
while IFS= read -r line || [[ -n "$line" ]]; do
|
|
63
|
+
if [[ "$line" =~ $heading ]]; then
|
|
64
|
+
printf '%s%s%s\n' "$h" "$line" "$r"
|
|
65
|
+
elif [[ "$line" == "Usage: "* ]]; then
|
|
66
|
+
printf '%sUsage:%s%s\n' "$h" "$r" "${line#Usage:}"
|
|
67
|
+
else
|
|
68
|
+
printf '%s\n' "$line"
|
|
69
|
+
fi
|
|
70
|
+
done
|
|
71
|
+
}
|
|
72
|
+
|
|
38
73
|
# =============================================================================
|
|
39
74
|
# Prompts
|
|
40
75
|
# =============================================================================
|
|
@@ -101,7 +136,7 @@ gb_choice() {
|
|
|
101
136
|
GB_CONFIG_KEYS="GITBASH_CREATE_BRANCH_PREFIX GITBASH_FEATURE_BRANCH_PREFIX GITBASH_MERGE_COMMAND \
|
|
102
137
|
GITBASH_CREATE_NO_ISSUE_PARSING GITBASH_CREATE_ISSUE_PARSING_FALLBACK GITBASH_CREATE_AUTO_PUSH \
|
|
103
138
|
GITBASH_THEME GITBASH_STALE_MONTHS GITBASH_CLEANUP_DAYS GITBASH_PROTECTED_BRANCHES \
|
|
104
|
-
GITBASH_BASE_BRANCH GITBASH_REMOTE"
|
|
139
|
+
GITBASH_BASE_BRANCH GITBASH_REMOTE GITBASH_NO_UPDATE_CHECKS GITBASH_RESET_KEEP"
|
|
105
140
|
|
|
106
141
|
_gb_config_key_allowed() {
|
|
107
142
|
[[ " $GB_CONFIG_KEYS " == *" $1 "* ]]
|
|
@@ -179,6 +214,7 @@ _gb_normalize_config() {
|
|
|
179
214
|
GITBASH_CREATE_ISSUE_PARSING_FALLBACK="${GITBASH_CREATE_ISSUE_PARSING_FALLBACK:-NOISSUE}"
|
|
180
215
|
GITBASH_PROTECTED_BRANCHES="${GITBASH_PROTECTED_BRANCHES:-main master develop release/*}"
|
|
181
216
|
GITBASH_BASE_BRANCH="${GITBASH_BASE_BRANCH:-}"
|
|
217
|
+
GITBASH_RESET_KEEP="${GITBASH_RESET_KEEP:-}"
|
|
182
218
|
|
|
183
219
|
case "${GITBASH_CREATE_NO_ISSUE_PARSING:-no}" in
|
|
184
220
|
yes|no) GITBASH_CREATE_NO_ISSUE_PARSING="${GITBASH_CREATE_NO_ISSUE_PARSING:-no}" ;;
|
|
@@ -195,6 +231,12 @@ _gb_normalize_config() {
|
|
|
195
231
|
*) print_warning "Invalid GITBASH_THEME '$GITBASH_THEME', using 'auto'."
|
|
196
232
|
GITBASH_THEME="auto" ;;
|
|
197
233
|
esac
|
|
234
|
+
case "${GITBASH_NO_UPDATE_CHECKS:-no}" in
|
|
235
|
+
yes|1|true) GITBASH_NO_UPDATE_CHECKS="yes" ;;
|
|
236
|
+
no|0|false) GITBASH_NO_UPDATE_CHECKS="no" ;;
|
|
237
|
+
*) print_warning "Invalid GITBASH_NO_UPDATE_CHECKS '$GITBASH_NO_UPDATE_CHECKS', using 'no'."
|
|
238
|
+
GITBASH_NO_UPDATE_CHECKS="no" ;;
|
|
239
|
+
esac
|
|
198
240
|
if ! [[ "${GITBASH_STALE_MONTHS:-3}" =~ ^[1-9][0-9]*$ ]]; then
|
|
199
241
|
print_warning "Invalid GITBASH_STALE_MONTHS '$GITBASH_STALE_MONTHS', using 3."
|
|
200
242
|
GITBASH_STALE_MONTHS=3
|
|
@@ -310,6 +352,29 @@ gb_base_ref() {
|
|
|
310
352
|
fi
|
|
311
353
|
}
|
|
312
354
|
|
|
355
|
+
# Fetch the current branch's upstream and, if it has new commits, offer to
|
|
356
|
+
# fast-forward. Returns 1 only when the fast-forward fails.
|
|
357
|
+
gb_offer_fast_forward() {
|
|
358
|
+
local branch upstream_remote upstream_merge behind
|
|
359
|
+
branch=$(gb_current_branch) || return 0
|
|
360
|
+
upstream_remote=$(git config "branch.$branch.remote" 2>/dev/null) || return 0
|
|
361
|
+
upstream_merge=$(git config "branch.$branch.merge" 2>/dev/null) || return 0
|
|
362
|
+
git fetch --quiet "$upstream_remote" "$upstream_merge" 2>/dev/null || return 0
|
|
363
|
+
behind=$(git rev-list --count "HEAD..@{upstream}" 2>/dev/null) || return 0
|
|
364
|
+
if [[ "$behind" -gt 0 ]]; then
|
|
365
|
+
print_warning "Branch is $behind commit(s) behind its upstream."
|
|
366
|
+
if gb_confirm "Fast-forward to the latest changes?" y; then
|
|
367
|
+
if git merge --ff-only --quiet "@{upstream}"; then
|
|
368
|
+
print_success "Up to date."
|
|
369
|
+
else
|
|
370
|
+
print_error "Could not fast-forward (you have local commits or changes). Run 'git pull' to reconcile."
|
|
371
|
+
return 1
|
|
372
|
+
fi
|
|
373
|
+
fi
|
|
374
|
+
fi
|
|
375
|
+
return 0
|
|
376
|
+
}
|
|
377
|
+
|
|
313
378
|
# Returns 0 if the branch is protected (base branch or GITBASH_PROTECTED_BRANCHES).
|
|
314
379
|
# Set GB_BASE beforehand to avoid detecting the base branch on every call.
|
|
315
380
|
gb_is_protected() {
|
|
@@ -454,9 +519,9 @@ gb_sync_and_push() {
|
|
|
454
519
|
# Previews
|
|
455
520
|
# =============================================================================
|
|
456
521
|
|
|
457
|
-
# Command that colors a diff read from stdin (delta if installed)
|
|
522
|
+
# Command that colors a diff read from stdin (delta if installed and colors are on)
|
|
458
523
|
gb_diff_pager() {
|
|
459
|
-
if command -v delta >/dev/null 2>&1; then
|
|
524
|
+
if [[ "$GB_COLOR" == "always" ]] && command -v delta >/dev/null 2>&1; then
|
|
460
525
|
case "${GITBASH_THEME:-auto}" in
|
|
461
526
|
dark) echo "delta --dark" ;;
|
|
462
527
|
light) echo "delta --light" ;;
|
|
@@ -480,9 +545,9 @@ gb_bat_cmd() {
|
|
|
480
545
|
return 0
|
|
481
546
|
fi
|
|
482
547
|
case "${GITBASH_THEME:-auto}" in
|
|
483
|
-
dark) echo "$bat --color
|
|
484
|
-
light) echo "$bat --color
|
|
485
|
-
*) echo "$bat --color
|
|
548
|
+
dark) echo "$bat --color=$GB_COLOR --style=numbers --theme=Dracula" ;;
|
|
549
|
+
light) echo "$bat --color=$GB_COLOR --style=numbers --theme=GitHub" ;;
|
|
550
|
+
*) echo "$bat --color=$GB_COLOR --style=numbers" ;;
|
|
486
551
|
esac
|
|
487
552
|
}
|
|
488
553
|
|
|
@@ -518,6 +583,52 @@ gb_urlencode() {
|
|
|
518
583
|
printf '%s' "$out"
|
|
519
584
|
}
|
|
520
585
|
|
|
586
|
+
# Convert a remote URL to the repository's web URL (credentials and .git removed).
|
|
587
|
+
# Handles https://[user[:token]@]host/path, ssh://[user@]host[:port]/path and user@host:path.
|
|
588
|
+
gb_web_url() {
|
|
589
|
+
local url="$1" scheme="https" rest host path
|
|
590
|
+
case "$url" in
|
|
591
|
+
http://*|https://*)
|
|
592
|
+
scheme="${url%%://*}"
|
|
593
|
+
rest="${url#*://}"
|
|
594
|
+
host="${rest%%/*}"
|
|
595
|
+
host="${host##*@}"
|
|
596
|
+
path="${rest#*/}"
|
|
597
|
+
;;
|
|
598
|
+
ssh://*)
|
|
599
|
+
rest="${url#ssh://}"
|
|
600
|
+
host="${rest%%/*}"
|
|
601
|
+
host="${host##*@}"
|
|
602
|
+
host="${host%%:*}"
|
|
603
|
+
path="${rest#*/}"
|
|
604
|
+
;;
|
|
605
|
+
*@*:*)
|
|
606
|
+
host="${url%%:*}"
|
|
607
|
+
host="${host##*@}"
|
|
608
|
+
path="${url#*:}"
|
|
609
|
+
;;
|
|
610
|
+
*)
|
|
611
|
+
return 1
|
|
612
|
+
;;
|
|
613
|
+
esac
|
|
614
|
+
path="${path%/}"
|
|
615
|
+
path="${path%.git}"
|
|
616
|
+
if [[ -z "$host" || -z "$path" || ( -n "$rest" && "$path" == "$rest" ) ]]; then
|
|
617
|
+
return 1
|
|
618
|
+
fi
|
|
619
|
+
|
|
620
|
+
# Azure DevOps SSH: ssh.dev.azure.com:v3/org/project/repo
|
|
621
|
+
if [[ "$host" == "ssh.dev.azure.com" && "$path" == v3/*/*/* ]]; then
|
|
622
|
+
local org project repo
|
|
623
|
+
path="${path#v3/}"
|
|
624
|
+
org="${path%%/*}"; path="${path#*/}"
|
|
625
|
+
project="${path%%/*}"; repo="${path#*/}"
|
|
626
|
+
echo "https://dev.azure.com/$org/$project/_git/$repo"
|
|
627
|
+
return 0
|
|
628
|
+
fi
|
|
629
|
+
echo "$scheme://$host/$path"
|
|
630
|
+
}
|
|
631
|
+
|
|
521
632
|
# Open a URL in the browser, or print it if no opener is available
|
|
522
633
|
gb_open_url() {
|
|
523
634
|
local url="$1"
|
package/commands/branch.sh
CHANGED
|
@@ -14,7 +14,7 @@ branch() {
|
|
|
14
14
|
return 0
|
|
15
15
|
fi
|
|
16
16
|
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
|
|
17
|
-
|
|
17
|
+
gb_help << 'EOF'
|
|
18
18
|
Usage: branch [OPTIONS]
|
|
19
19
|
|
|
20
20
|
Interactive menu to manage git branches.
|
|
@@ -86,8 +86,8 @@ Examples:
|
|
|
86
86
|
✓ 'feature/PROJ-123-add-new-feature' is now up-to-date with 'main'.
|
|
87
87
|
|
|
88
88
|
Actions:
|
|
89
|
-
🌿 Create
|
|
90
|
-
🔀 Switch
|
|
89
|
+
🌿 Create - Create a new feature branch with Jira parsing
|
|
90
|
+
🔀 Switch - Switch to another branch using fzf
|
|
91
91
|
⬆️ Update - Update current branch with latest main/master
|
|
92
92
|
|
|
93
93
|
Requirements:
|
package/commands/cleanstash.sh
CHANGED
package/commands/cleanup.sh
CHANGED
|
@@ -37,7 +37,7 @@ cleanup() {
|
|
|
37
37
|
return 0
|
|
38
38
|
;;
|
|
39
39
|
-h|--help)
|
|
40
|
-
|
|
40
|
+
gb_help << 'EOF'
|
|
41
41
|
Usage: cleanup [OPTIONS]
|
|
42
42
|
|
|
43
43
|
Find and delete local branches that are no longer needed.
|
|
@@ -178,7 +178,7 @@ EOF
|
|
|
178
178
|
fi
|
|
179
179
|
entries+=("$preselect|$label|$ts|$branch|$rel|$email|$unpushed|$name")
|
|
180
180
|
done < <(git for-each-ref \
|
|
181
|
-
--format="%(refname:short)%1f%(committerdate:unix)%1f%(committerdate:relative)%1f%(
|
|
181
|
+
--format="%(refname:short)%1f%(committerdate:unix)%1f%(committerdate:relative)%1f%(authoremail)%1f%(upstream:short)%1f%(upstream:track)%1f%(authorname)" \
|
|
182
182
|
refs/heads 2>/dev/null)
|
|
183
183
|
|
|
184
184
|
# Pre-selected first, then newest first
|
|
@@ -273,14 +273,14 @@ ${#sorted[@]} branches, $preselect_count pre-selected" \
|
|
|
273
273
|
if [[ -z "$branch" ]]; then echo "Exit without action"; exit 0; fi
|
|
274
274
|
echo "Branch: $branch"
|
|
275
275
|
echo
|
|
276
|
-
unpushed=$(git log --oneline --color
|
|
276
|
+
unpushed=$(git log --oneline --color=$GB_COLOR "refs/heads/$branch" --not --remotes 2>/dev/null)
|
|
277
277
|
if [[ -n "$unpushed" ]]; then
|
|
278
278
|
echo "Unpushed commits (only on this machine):"
|
|
279
279
|
echo "$unpushed"
|
|
280
280
|
echo
|
|
281
281
|
fi
|
|
282
282
|
echo "Recent commits:"
|
|
283
|
-
git log --oneline --color
|
|
283
|
+
git log --oneline --color=$GB_COLOR -n 15 "refs/heads/$branch" 2>/dev/null
|
|
284
284
|
' \
|
|
285
285
|
--preview-window=right:40% \
|
|
286
286
|
--bind "load:$toggle_sequence" \
|
package/commands/commit.sh
CHANGED
package/commands/commits.sh
CHANGED
|
@@ -5,21 +5,28 @@ SOURCE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
5
5
|
# shellcheck source=_utils.sh
|
|
6
6
|
source "$SOURCE_DIR/_utils.sh"
|
|
7
7
|
|
|
8
|
-
# List
|
|
8
|
+
# List the current branch's own commits and optionally revert selected ones
|
|
9
9
|
commits() {
|
|
10
10
|
if [[ "${1:-}" == "-v" || "${1:-}" == "--version" ]]; then
|
|
11
11
|
echo "gitbash ${FUNCNAME[0]} v$VERSION"
|
|
12
12
|
return 0
|
|
13
13
|
fi
|
|
14
14
|
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
|
|
15
|
-
|
|
16
|
-
Usage: commits [COUNT]
|
|
15
|
+
gb_help << 'EOF'
|
|
16
|
+
Usage: commits [-a|--all] [COUNT]
|
|
17
17
|
|
|
18
|
-
List
|
|
18
|
+
List the commits made on the current branch with option to revert selected ones.
|
|
19
|
+
|
|
20
|
+
On a feature branch only the commits that are not in the base branch are
|
|
21
|
+
shown. On the base branch its own history is shown (--first-parent), so
|
|
22
|
+
merged branches appear as their merge commit.
|
|
19
23
|
|
|
20
24
|
Arguments:
|
|
21
25
|
COUNT Number of commits to show (default: 20)
|
|
22
26
|
|
|
27
|
+
Options:
|
|
28
|
+
-a, --all Show all recent commits reachable from HEAD
|
|
29
|
+
|
|
23
30
|
Navigation:
|
|
24
31
|
↑/↓ Navigate through commits
|
|
25
32
|
TAB Select/deselect commit for revert
|
|
@@ -27,6 +34,7 @@ Navigation:
|
|
|
27
34
|
ESC/Ctrl-C Exit without action
|
|
28
35
|
|
|
29
36
|
Notes:
|
|
37
|
+
- If the upstream has new commits, offers to fast-forward first
|
|
30
38
|
- Preview shows the full commit diff
|
|
31
39
|
- Selected commits are reverted newest first, whatever order you picked them in
|
|
32
40
|
- Merge commits are reverted against their first parent (the branch they were merged into)
|
|
@@ -35,6 +43,7 @@ Notes:
|
|
|
35
43
|
Examples:
|
|
36
44
|
$ commits
|
|
37
45
|
$ commits 50
|
|
46
|
+
$ commits --all
|
|
38
47
|
|
|
39
48
|
Requirements:
|
|
40
49
|
- Must be in a git repository
|
|
@@ -46,16 +55,56 @@ EOF
|
|
|
46
55
|
|
|
47
56
|
require_git_repo || return 1
|
|
48
57
|
|
|
49
|
-
local count="
|
|
58
|
+
local all=false count=""
|
|
59
|
+
while [[ $# -gt 0 ]]; do
|
|
60
|
+
case "$1" in
|
|
61
|
+
-a|--all) all=true ;;
|
|
62
|
+
-*) print_error "Unknown option '$1'. See 'commits --help'."; return 1 ;;
|
|
63
|
+
*)
|
|
64
|
+
if [[ -n "$count" ]]; then
|
|
65
|
+
print_error "Unexpected argument '$1'. See 'commits --help'."
|
|
66
|
+
return 1
|
|
67
|
+
fi
|
|
68
|
+
count="$1"
|
|
69
|
+
;;
|
|
70
|
+
esac
|
|
71
|
+
shift
|
|
72
|
+
done
|
|
73
|
+
count="${count:-20}"
|
|
50
74
|
if ! [[ "$count" =~ ^[1-9][0-9]*$ ]]; then
|
|
51
75
|
print_error "COUNT must be a positive number (got '$count')."
|
|
52
76
|
return 1
|
|
53
77
|
fi
|
|
54
78
|
require_fzf || return 1
|
|
55
79
|
|
|
80
|
+
# Offer to pull remote commits first, so they show up (and can be reverted)
|
|
81
|
+
gb_offer_fast_forward || true
|
|
82
|
+
|
|
56
83
|
local current_branch
|
|
57
84
|
current_branch=$(gb_current_branch) || current_branch="(detached HEAD)"
|
|
58
85
|
|
|
86
|
+
# -----------------------------
|
|
87
|
+
# Which commits: the branch's own (not in the base branch) or, on the
|
|
88
|
+
# base branch, its first-parent history
|
|
89
|
+
# -----------------------------
|
|
90
|
+
local log_args=() scope="last $count commits" empty_hint="" base_branch base_ref
|
|
91
|
+
if [[ "$all" == false ]] && base_branch=$(gb_base_branch 2>/dev/null); then
|
|
92
|
+
base_ref=$(gb_base_ref "$base_branch")
|
|
93
|
+
if [[ "$current_branch" == "$base_branch" ]]; then
|
|
94
|
+
log_args=(--first-parent)
|
|
95
|
+
scope="last $count commits on '$base_branch' (merged branches as merge commits)"
|
|
96
|
+
elif git rev-parse --verify --quiet "$base_ref^{commit}" >/dev/null; then
|
|
97
|
+
log_args=(--not "$base_ref")
|
|
98
|
+
# Also exclude the local base branch when it is ahead of the remote one
|
|
99
|
+
if [[ "$base_ref" != "$base_branch" ]] &&
|
|
100
|
+
git show-ref --verify --quiet "refs/heads/$base_branch"; then
|
|
101
|
+
log_args+=("$base_branch")
|
|
102
|
+
fi
|
|
103
|
+
scope="commits not in '$base_ref' (up to $count)"
|
|
104
|
+
empty_hint="No commits on '$current_branch' that are not in '$base_ref'. Use 'commits --all' to show all recent commits."
|
|
105
|
+
fi
|
|
106
|
+
fi
|
|
107
|
+
|
|
59
108
|
# -----------------------------
|
|
60
109
|
# Build commit list (fields separated by \x1f, subject last)
|
|
61
110
|
# -----------------------------
|
|
@@ -67,10 +116,10 @@ EOF
|
|
|
67
116
|
fi
|
|
68
117
|
commit_list+=$(printf "%-10s %-60s %-15s %s" "$hash" "$subject" "$date" "$author")
|
|
69
118
|
commit_list+=$'\t'"$hash"$'\n'
|
|
70
|
-
done < <(git log -n "$count" --format='%h%x1f%cr%x1f%an%x1f%s' 2>/dev/null)
|
|
119
|
+
done < <(git log -n "$count" --format='%h%x1f%cr%x1f%an%x1f%s' HEAD ${log_args[@]+"${log_args[@]}"} 2>/dev/null)
|
|
71
120
|
|
|
72
121
|
if [[ -z "$commit_list" ]]; then
|
|
73
|
-
echo "No commits found."
|
|
122
|
+
echo "${empty_hint:-No commits found.}"
|
|
74
123
|
return 0
|
|
75
124
|
fi
|
|
76
125
|
|
|
@@ -78,11 +127,11 @@ EOF
|
|
|
78
127
|
pager=$(gb_diff_pager)
|
|
79
128
|
preview='
|
|
80
129
|
hash=$(printf "%s" {} | cut -f2)
|
|
81
|
-
git show --stat --color
|
|
130
|
+
git show --stat --color=$GB_COLOR "$hash" 2>/dev/null
|
|
82
131
|
echo
|
|
83
132
|
echo "─────────────────────────────────────────────────────"
|
|
84
133
|
echo
|
|
85
|
-
git show --color
|
|
134
|
+
git show --color=$GB_COLOR --format= "$hash" 2>/dev/null | head -300 | __PAGER__'
|
|
86
135
|
preview="${preview//__PAGER__/$pager}"
|
|
87
136
|
|
|
88
137
|
local selection
|
|
@@ -92,7 +141,7 @@ EOF
|
|
|
92
141
|
--reverse \
|
|
93
142
|
--border \
|
|
94
143
|
--header="[TAB] select for revert | [Enter] revert selected | [ESC] exit
|
|
95
|
-
Showing
|
|
144
|
+
Showing $scope" \
|
|
96
145
|
--multi \
|
|
97
146
|
--delimiter=$'\t' \
|
|
98
147
|
--with-nth=1 \
|
package/commands/create.sh
CHANGED
package/commands/pr.sh
CHANGED
|
@@ -5,52 +5,6 @@ SOURCE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
5
5
|
# shellcheck source=_utils.sh
|
|
6
6
|
source "$SOURCE_DIR/_utils.sh"
|
|
7
7
|
|
|
8
|
-
# Convert a remote URL to the repository's web URL (credentials and .git removed).
|
|
9
|
-
# Handles https://[user[:token]@]host/path, ssh://[user@]host[:port]/path and user@host:path.
|
|
10
|
-
_pr_web_base() {
|
|
11
|
-
local url="$1" scheme="https" rest host path
|
|
12
|
-
case "$url" in
|
|
13
|
-
http://*|https://*)
|
|
14
|
-
scheme="${url%%://*}"
|
|
15
|
-
rest="${url#*://}"
|
|
16
|
-
host="${rest%%/*}"
|
|
17
|
-
host="${host##*@}"
|
|
18
|
-
path="${rest#*/}"
|
|
19
|
-
;;
|
|
20
|
-
ssh://*)
|
|
21
|
-
rest="${url#ssh://}"
|
|
22
|
-
host="${rest%%/*}"
|
|
23
|
-
host="${host##*@}"
|
|
24
|
-
host="${host%%:*}"
|
|
25
|
-
path="${rest#*/}"
|
|
26
|
-
;;
|
|
27
|
-
*@*:*)
|
|
28
|
-
host="${url%%:*}"
|
|
29
|
-
host="${host##*@}"
|
|
30
|
-
path="${url#*:}"
|
|
31
|
-
;;
|
|
32
|
-
*)
|
|
33
|
-
return 1
|
|
34
|
-
;;
|
|
35
|
-
esac
|
|
36
|
-
path="${path%/}"
|
|
37
|
-
path="${path%.git}"
|
|
38
|
-
if [[ -z "$host" || -z "$path" || ( -n "$rest" && "$path" == "$rest" ) ]]; then
|
|
39
|
-
return 1
|
|
40
|
-
fi
|
|
41
|
-
|
|
42
|
-
# Azure DevOps SSH: ssh.dev.azure.com:v3/org/project/repo
|
|
43
|
-
if [[ "$host" == "ssh.dev.azure.com" && "$path" == v3/*/*/* ]]; then
|
|
44
|
-
local org project repo
|
|
45
|
-
path="${path#v3/}"
|
|
46
|
-
org="${path%%/*}"; path="${path#*/}"
|
|
47
|
-
project="${path%%/*}"; repo="${path#*/}"
|
|
48
|
-
echo "https://dev.azure.com/$org/$project/_git/$repo"
|
|
49
|
-
return 0
|
|
50
|
-
fi
|
|
51
|
-
echo "$scheme://$host/$path"
|
|
52
|
-
}
|
|
53
|
-
|
|
54
8
|
# Web URL for creating a pull/merge request for a branch
|
|
55
9
|
_pr_create_url() {
|
|
56
10
|
local base="$1" branch="$2" encoded
|
|
@@ -83,7 +37,7 @@ pr() {
|
|
|
83
37
|
return 0
|
|
84
38
|
;;
|
|
85
39
|
-h|--help)
|
|
86
|
-
|
|
40
|
+
gb_help << 'EOF'
|
|
87
41
|
Usage: pr [OPTIONS]
|
|
88
42
|
|
|
89
43
|
Open the current branch's pull request in your browser.
|
|
@@ -147,7 +101,7 @@ EOF
|
|
|
147
101
|
print_error "Detached HEAD: check out a branch first."
|
|
148
102
|
return 1
|
|
149
103
|
fi
|
|
150
|
-
if ! base=$(
|
|
104
|
+
if ! base=$(gb_web_url "$remote_url"); then
|
|
151
105
|
print_error "Don't know how to open '$remote_url' in a browser."
|
|
152
106
|
return 1
|
|
153
107
|
fi
|
package/commands/repo.sh
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
# Source common utilities
|
|
4
|
+
SOURCE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
5
|
+
# shellcheck source=_utils.sh
|
|
6
|
+
source "$SOURCE_DIR/_utils.sh"
|
|
7
|
+
|
|
8
|
+
# Open the repository's web page
|
|
9
|
+
repo() {
|
|
10
|
+
local print_only=false
|
|
11
|
+
|
|
12
|
+
while [[ $# -gt 0 ]]; do
|
|
13
|
+
case "$1" in
|
|
14
|
+
-v|--version)
|
|
15
|
+
echo "gitbash ${FUNCNAME[0]} v$VERSION"
|
|
16
|
+
return 0
|
|
17
|
+
;;
|
|
18
|
+
-h|--help)
|
|
19
|
+
gb_help << 'EOF_HELP'
|
|
20
|
+
Usage: repo [OPTIONS]
|
|
21
|
+
|
|
22
|
+
Open the repository's web page in your browser.
|
|
23
|
+
|
|
24
|
+
Options:
|
|
25
|
+
--print Print the URL instead of opening it
|
|
26
|
+
-h, --help Show this help message
|
|
27
|
+
|
|
28
|
+
Behavior:
|
|
29
|
+
- Uses the URL of the configured remote (GITBASH_REMOTE, default: origin)
|
|
30
|
+
- With the GitHub CLI (gh) installed and logged in, opens it with 'gh repo view --web'
|
|
31
|
+
- Otherwise opens the URL derived from the remote
|
|
32
|
+
(GitHub, GitHub Enterprise, GitLab, Bitbucket, Azure DevOps)
|
|
33
|
+
- Works with SSH and HTTPS remotes; credentials in the remote URL are never used
|
|
34
|
+
- Opens the browser with 'open' (macOS) or 'xdg-open' (Linux), otherwise prints the URL
|
|
35
|
+
|
|
36
|
+
Examples:
|
|
37
|
+
$ repo
|
|
38
|
+
$ repo --print
|
|
39
|
+
|
|
40
|
+
EOF_HELP
|
|
41
|
+
return 0
|
|
42
|
+
;;
|
|
43
|
+
--print)
|
|
44
|
+
print_only=true
|
|
45
|
+
shift
|
|
46
|
+
;;
|
|
47
|
+
*)
|
|
48
|
+
print_error "Unknown argument: $1"
|
|
49
|
+
echo "Usage: repo [--print]" >&2
|
|
50
|
+
return 1
|
|
51
|
+
;;
|
|
52
|
+
esac
|
|
53
|
+
done
|
|
54
|
+
|
|
55
|
+
require_git_repo || return 1
|
|
56
|
+
|
|
57
|
+
local remote remote_url url
|
|
58
|
+
remote=$(gb_remote)
|
|
59
|
+
if ! remote_url=$(git config --get "remote.$remote.url"); then
|
|
60
|
+
print_error "No remote '$remote' found."
|
|
61
|
+
return 1
|
|
62
|
+
fi
|
|
63
|
+
if ! url=$(gb_web_url "$remote_url"); then
|
|
64
|
+
print_error "Don't know how to open '$remote_url' in a browser."
|
|
65
|
+
return 1
|
|
66
|
+
fi
|
|
67
|
+
|
|
68
|
+
if [[ "$print_only" == true ]]; then
|
|
69
|
+
echo "$url"
|
|
70
|
+
return 0
|
|
71
|
+
fi
|
|
72
|
+
|
|
73
|
+
if [[ "$url" != *gitlab* && "$url" != *bitbucket.org/* && "$url" != *dev.azure.com/* && "$url" != *visualstudio.com/* ]] &&
|
|
74
|
+
command -v gh >/dev/null 2>&1; then
|
|
75
|
+
if GH_PROMPT_DISABLED=1 gh repo view "$url" --web >/dev/null 2>&1; then
|
|
76
|
+
print_success "Opened $url"
|
|
77
|
+
return 0
|
|
78
|
+
fi
|
|
79
|
+
fi
|
|
80
|
+
|
|
81
|
+
gb_open_url "$url"
|
|
82
|
+
}
|