gitbash 3.1.0 → 3.1.1

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 CHANGED
@@ -151,7 +151,7 @@ create --no-push PROJ-7 quick fix # → feature/PROJ-7-quick-fix, not push
151
151
  switch [FILTER...]
152
152
  ```
153
153
 
154
- Switch branches with fzf. Shows local branches (`merged:` = fully merged into the base branch), then remote branches without a local copy. Preview shows commit history. Switches directly when the filter is an exact branch name or matches exactly one branch name. After switching, offers to fast-forward a branch that is behind.
154
+ Switch branches with fzf. Shows local branches (`merged:` = fully merged into the base branch), then remote branches without a local copy. Preview shows commit history. Switches directly when the filter is an exact branch name or matches exactly one branch name; a branch name that is not known locally is fetched from the remote first, so `switch <branch>` also works for a branch pushed since the last fetch. After switching, offers to fast-forward a branch that is behind.
155
155
 
156
156
  - `Del` deletes the selected local branch (asks first, default no; unmerged commits need a second confirmation)
157
157
 
@@ -437,6 +437,30 @@ gb_ref_short() {
437
437
  echo "${ref#refs/heads/}"
438
438
  }
439
439
 
440
+ # Fetch all branches of the remote and prune deleted ones, for commands that
441
+ # can go on with local data. On failure, warns with git's own error.
442
+ # git fails when a single ref can't be updated, even if all others were: on a
443
+ # case-insensitive file system (macOS, Windows) it does so on every fetch when
444
+ # the remote has branches whose names differ only in case (Feature/x, feature/x).
445
+ # Usage: gb_fetch_prune <remote> [--silent]
446
+ gb_fetch_prune() {
447
+ local remote="$1" silent="${2:-}" err refs
448
+ err=$(git fetch --prune --quiet "$remote" 2>&1 >/dev/null) && return 0
449
+ [[ "$silent" == "--silent" ]] && return 1
450
+
451
+ refs=$(printf '%s\n' "$err" | sed -n "s/^error: cannot lock ref 'refs\/remotes\/\([^']*\)'.*/\1/p" | sort -u)
452
+ if [[ -n "$refs" ]]; then
453
+ print_warning "Fetch could not update $(printf '%s\n' "$refs" | paste -sd ' ' -); all other branches were updated."
454
+ if [[ "$(git config --bool core.ignoreCase 2>/dev/null)" == "true" ]]; then
455
+ print_info "The remote probably has branches whose names differ only in case, which this file system can't keep apart. Delete or rename one of them on the remote, or store refs case-sensitively with 'git refs migrate --ref-format=reftable' (git 2.46+)."
456
+ fi
457
+ else
458
+ print_warning "Fetch failed; continuing with local data."
459
+ fi
460
+ printf '%s\n' "$err" | gb_sanitize | grep -v '^[[:space:]]*$' | head -n 5 | sed 's/^/ /' >&2
461
+ return 1
462
+ }
463
+
440
464
  # Fetch the current branch's upstream and, if it has new commits, offer to
441
465
  # fast-forward. Returns 1 only when the fast-forward fails.
442
466
  gb_offer_fast_forward() {
@@ -134,8 +134,10 @@ EOF
134
134
 
135
135
  local remote
136
136
  remote=$(gb_remote)
137
- if ! git fetch --prune --quiet "$remote" 2>/dev/null; then
138
- [[ "$json_mode" == false ]] && print_warning "Fetch failed; continuing with local data."
137
+ if [[ "$json_mode" == true ]]; then
138
+ gb_fetch_prune "$remote" --silent
139
+ else
140
+ gb_fetch_prune "$remote"
139
141
  fi
140
142
 
141
143
  local base_branch base_ref
package/commands/stale.sh CHANGED
@@ -132,8 +132,10 @@ EOF
132
132
  local remote
133
133
  remote=$(gb_remote)
134
134
  [[ "$json_mode" == false ]] && echo "Fetching latest from '$remote'..."
135
- if ! git fetch --prune --quiet "$remote" 2>/dev/null; then
136
- [[ "$json_mode" == false ]] && print_warning "Fetch failed; continuing with local data."
135
+ if [[ "$json_mode" == true ]]; then
136
+ gb_fetch_prune "$remote" --silent
137
+ else
138
+ gb_fetch_prune "$remote"
137
139
  fi
138
140
  GB_BASE=$(gb_base_branch 2>/dev/null) || GB_BASE=""
139
141
 
@@ -39,6 +39,16 @@ _switch_list_branches() {
39
39
  done < <(git for-each-ref --format='%(refname:lstrip=2)' refs/remotes)
40
40
  }
41
41
 
42
+ # Fetch one branch from the remote ("<name>" or "<remote>/<name>").
43
+ # Returns 1 if it is not a valid branch name or the remote has no such branch.
44
+ _switch_fetch_branch() {
45
+ local remote name
46
+ remote=$(gb_remote)
47
+ name="${1#"$remote"/}"
48
+ _gb_valid_branch_name "$name" || return 1
49
+ git fetch --quiet "$remote" "+refs/heads/$name:refs/remotes/$remote/$name" 2>/dev/null
50
+ }
51
+
42
52
  # Delete the local branch of a list line (called from fzf via 'switch --delete-branch')
43
53
  _switch_delete_branch() {
44
54
  local line="$1" type name current count
@@ -110,7 +120,8 @@ Select a git branch using fzf and switch to it.
110
120
  Arguments:
111
121
  FILTER... Optional search words to pre-fill fzf (joined with spaces).
112
122
  Switches directly on an exact branch name, or if exactly
113
- one branch name contains them.
123
+ one branch name contains them. A branch that is not known
124
+ locally is fetched from the remote first.
114
125
 
115
126
  Options:
116
127
  -h, --help Show this help message
@@ -176,6 +187,17 @@ EOF
176
187
  fi
177
188
  [[ -n "$selected" ]] && print_info "Exact match found, switching directly..."
178
189
  fi
190
+ # Not in the list: it may be a branch that was pushed since the last fetch
191
+ if [[ -n "$filter" && -z "$selected" ]] && _switch_fetch_branch "$filter"; then
192
+ local remote name
193
+ remote=$(gb_remote)
194
+ name="${filter#"$remote"/}"
195
+ branch_list=$(_switch_list_branches)
196
+ # (the list shows the local branch instead, if "<remote>/<name>" has one)
197
+ selected=$(printf '%s\n' "$branch_list" | awk -F'\t' -v r="$remote/$name" -v n="$name" \
198
+ '($2 == "remote" && $3 == r) || ($2 == "local" && $3 == n) { print; exit }')
199
+ [[ -n "$selected" ]] && print_info "Found on $remote, switching directly..."
200
+ fi
179
201
  if [[ -n "$filter" && -z "$selected" ]]; then
180
202
  local matches match_count
181
203
  matches=$(printf '%s\n' "$branch_list" | awk -F'\t' '$2 != "spacer"' |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gitbash",
3
- "version": "3.1.0",
3
+ "version": "3.1.1",
4
4
  "description": "Opinionated git utilities for bash with fzf-powered menus",
5
5
  "author": "jaggli",
6
6
  "license": "MIT",
@@ -52,7 +52,7 @@
52
52
  "version": "changeset version"
53
53
  },
54
54
  "devDependencies": {
55
- "@changesets/cli": "^2.29.8",
55
+ "@changesets/cli": "^3.0.3",
56
56
  "bats": "^1.13.0"
57
57
  }
58
58
  }