gitbash 2.0.1 → 2.2.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 CHANGED
@@ -6,57 +6,103 @@ Pure bash, zero-dependency git utilities. Reduce repetitive typing and superchar
6
6
 
7
7
  ## Installation
8
8
 
9
- ### Via npm
9
+ Needs git >= 2.23 and bash >= 3.2. fzf (menus), delta (diffs) and bat (previews) are optional but recommended.
10
+
11
+ ### macOS
12
+
13
+ ```bash
14
+ npm i -g gitbash
15
+ brew install fzf git-delta bat
16
+ gitbash --config
17
+ ```
18
+
19
+ Shell integration (lets you type `commit` instead of `gitbash commit`):
10
20
 
11
21
  ```bash
12
- npm i -g gitbash && gitbash --config
22
+ ## for bash
23
+ echo 'eval "$(gitbash --init)"' >> ~/.bashrc
24
+
25
+ ## for zsh
26
+ echo 'eval "$(gitbash --init)"' >> ~/.zshrc
13
27
  ```
14
28
 
15
- ### Options
29
+ ### Linux
16
30
 
17
31
  ```bash
18
- gitbash --help # Show help
19
- gitbash --version # Show version
20
- gitbash --init # Print shell functions (see Shell integration)
21
- gitbash --config # Interactive configuration wizard
22
- gitbash --config-local # Configure overrides for the current repository (committed)
23
- gitbash --config-user # Configure personal overrides for the current repository
32
+ npm i -g gitbash
33
+ sudo apt install fzf git-delta bat # Debian/Ubuntu, needs fzf >= 0.36
34
+ gitbash --config
24
35
  ```
25
36
 
26
- ### Dependencies
37
+ Shell integration:
27
38
 
28
39
  ```bash
29
- # Required
30
- git >= 2.23, bash >= 3.2
40
+ ## for bash
41
+ echo 'eval "$(gitbash --init)"' >> ~/.bashrc
31
42
 
32
- # Optional (recommended)
33
- brew install fzf # Interactive menus and previews (fzf >= 0.36)
34
- brew install git-delta # Better diff highlighting
35
- brew install bat # File preview with syntax highlighting
43
+ ## for zsh
44
+ echo 'eval "$(gitbash --init)"' >> ~/.zshrc
36
45
  ```
37
46
 
38
- ### Shell integration
47
+ ### Windows
39
48
 
40
- Add to your `.zshrc` or `.bashrc` to call the commands without the `gitbash` prefix:
49
+ In Git Bash (part of [Git for Windows](https://gitforwindows.org)); in WSL, follow the Linux steps:
41
50
 
42
51
  ```bash
43
- eval "$(gitbash --init)" # commit, switch, status, ...
44
- eval "$(gitbash --init --prefix=gb-)" # gb-commit, gb-switch, ... (avoids shadowing e.g. /usr/bin/pr)
52
+ npm i -g gitbash
53
+ winget install junegunn.fzf dandavison.delta sharkdp.bat # needs fzf >= 0.54
54
+ gitbash --config
45
55
  ```
46
56
 
47
- This defines small wrapper functions; every command still runs in its own bash process, so nothing else is added to your shell. Individual aliases work too, e.g. `alias commit="gitbash commit"`.
57
+ Shell integration for Git Bash:
48
58
 
49
- ### Upgrading to 2.0
59
+ ```bash
60
+ echo 'eval "$(gitbash --init)"' >> ~/.bashrc
61
+ ```
62
+
63
+ Shell integration for PowerShell: create the functions in Git Bash, then load them in your profile in PowerShell:
50
64
 
51
- 2.0 is a security and safety release. What changes for you:
65
+ ```bash
66
+ gitbash --init --shell=pwsh > ~/gitbash.ps1 # switch is a PowerShell keyword: use gitbash switch
67
+ ```
68
+
69
+ This creates your PowerShell profile if needed, loads `gitbash.ps1` from it in every new window, and allows local scripts to run (Windows PowerShell 5.1 blocks them by default):
70
+
71
+ ```powershell
72
+ if (!(Test-Path $PROFILE)) { New-Item -Force $PROFILE }
73
+ Add-Content $PROFILE '. ~/gitbash.ps1'
74
+ Set-ExecutionPolicy -Scope CurrentUser RemoteSigned # Windows PowerShell 5.1 only
75
+ ```
76
+
77
+ ### Without npm
78
+
79
+ Installation by script on machines without npm available
80
+
81
+ ```bash
82
+ # macOS, Linux, Git Bash (or: wget -qO- ... | sh)
83
+ curl -fsSL https://raw.githubusercontent.com/jaggli/gitbash/main/install.sh | sh
84
+ ```
85
+
86
+ ```powershell
87
+ # Windows PowerShell (needs Git for Windows)
88
+ irm https://raw.githubusercontent.com/jaggli/gitbash/main/install.ps1 | iex
89
+ ```
52
90
 
53
- - **Restart your shell** after upgrading, so `eval "$(gitbash --init)"` picks up the new wrapper functions.
54
- - Config files are **read, not executed**: only plain `GITBASH_*="value"` lines are used, other lines are ignored with a warning. `GITBASH_MERGE_COMMAND` is ignored in a committed `.gitbashrc`.
55
- - `status` no longer commits and pushes after staging. Use `Ctrl-O` to commit.
56
- - `stale` toggles all/stale branches with `Ctrl-T` (was `Ctrl-A`).
57
- - Protected branches (base branch and `GITBASH_PROTECTED_BRANCHES`) are never offered for deletion. `cleanup` and `switch` delete with `git branch -d` and ask again before force-deleting unmerged work.
58
- - When your branch and the remote diverged, `commit -p`, `pr -p` and `update -p` ask whether to rebase, merge or abort instead of rebasing silently.
59
- - fzf 0.36 or newer is required for the interactive menus.
91
+ It installs to `~/.local/share/gitbash` and links `~/.local/bin/gitbash` (add that folder to your PATH if the script says so); delete both to uninstall. Set `GITBASH_VERSION` for a specific version, and `GITBASH_INSTALL_DIR` / `GITBASH_BIN_DIR` for other locations.
92
+
93
+ ## Options
94
+
95
+ | Option | Description |
96
+ | --- | --- |
97
+ | `-h`, `--help` | Show the help |
98
+ | `-v`, `--version` | Show the version |
99
+ | `--update` | Update to the latest release (npm, pnpm or install script) |
100
+ | `--init` | Print shell functions to call commands without the `gitbash` prefix |
101
+ | `--init --prefix=gb-` | Prefixed functions: `gb-commit`, `gb-switch`, ... (avoids shadowing e.g. `/usr/bin/pr`) |
102
+ | `--init --shell=pwsh` | PowerShell functions instead of bash/zsh |
103
+ | `--config` | Configuration wizard (`~/.gitbashrc`); offers to install dependencies and the shell integration |
104
+ | `--config-local` | Overrides for the current repository (`.gitbashrc`, committed) |
105
+ | `--config-user` | Personal overrides for the current repository (`.gitbashrc-user`, not committed) |
60
106
 
61
107
  ## Commands
62
108
 
@@ -115,7 +161,7 @@ create enhance login screen # → feature/enhance-login-screen (pars
115
161
  switch [FILTER...]
116
162
  ```
117
163
 
118
- 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. If exactly one branch name matches the filter, switches directly. After switching, offers to fast-forward a branch that is behind.
164
+ 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.
119
165
 
120
166
  - `Del` deletes the selected local branch (asks first, default no; unmerged commits need a second confirmation)
121
167
 
@@ -162,6 +208,22 @@ pr [-p|--push] [--print]
162
208
 
163
209
  Open the pull request in the browser: the existing PR via the GitHub CLI when available, otherwise the create page (GitHub, GitHub Enterprise, GitLab, Bitbucket, Azure DevOps). Offers to commit local changes and to push a branch that is not on the remote yet. `-p` pushes first, `--print` prints the URL.
164
210
 
211
+ ### repo
212
+
213
+ ```bash
214
+ repo [--print]
215
+ ```
216
+
217
+ Open the repository's web page in the browser: via the GitHub CLI (`gh repo view --web`) when available, otherwise the URL derived from the remote (GitHub, GitHub Enterprise, GitLab, Bitbucket, Azure DevOps). `--print` prints the URL.
218
+
219
+ ### reset-repo
220
+
221
+ ```bash
222
+ reset-repo [-n|--dry-run] [-y|--yes]
223
+ ```
224
+
225
+ Reset the current branch like a fresh clone: fetch, `git reset --hard <remote>/<branch>` and delete all untracked and ignored files (`git clean -dx`). Lists the unpushed commits, local changes and files it removes and asks first. Aborts an unfinished merge or rebase. Files matching `GITBASH_RESET_KEEP` (e.g. `.env`), `.gitbashrc-user` and nested repositories are kept; stashes and other branches are not touched.
226
+
165
227
  ### update
166
228
 
167
229
  ```bash
@@ -238,14 +300,15 @@ Unpushed commits are shown per branch. Deletes with `git branch -d`; force-delet
238
300
  ### commits
239
301
 
240
302
  ```bash
241
- commits [COUNT]
303
+ commits [-a|--all] [COUNT]
242
304
  ```
243
305
 
244
- List recent commits with option to revert. Multi-select with TAB; selected commits are reverted newest first.
306
+ List the current branch's own commits with option to revert. On a feature branch only commits not in the base branch are shown; on the base branch its first-parent history (merged branches as their merge commit). If the upstream has new commits, offers to fast-forward first. Multi-select with TAB; selected commits are reverted newest first.
245
307
 
246
308
  ```bash
247
- commits # Show last 20 commits
248
- commits 50 # Show last 50 commits
309
+ commits # Show the branch's last 20 commits
310
+ commits 50 # Show up to 50
311
+ commits --all # All recent commits, like git log
249
312
  ```
250
313
 
251
314
  ## Configuration
@@ -278,11 +341,17 @@ GITBASH_CLEANUP_DAYS="7"
278
341
  # Branches never offered for deletion, space-separated globs
279
342
  GITBASH_PROTECTED_BRANCHES="main master develop release/*"
280
343
 
344
+ # Files 'reset-repo' keeps, space-separated .gitignore patterns, e.g. ".env .idea/" (default: "")
345
+ GITBASH_RESET_KEEP=""
346
+
281
347
  # Base branch (default: detected from origin/HEAD, then main, then master)
282
348
  GITBASH_BASE_BRANCH=""
283
349
 
284
350
  # Remote name (default: "origin")
285
351
  GITBASH_REMOTE="origin"
352
+
353
+ # Turn off the automatic update checks: yes or no (default: "no")
354
+ GITBASH_NO_UPDATE_CHECKS="no"
286
355
  ```
287
356
 
288
357
  Config files are **read, never executed**. Only `GITBASH_*="value"` lines are used (double, single or no quotes, optional `export`, `# comments`). Values cannot contain `$`, backticks, backslashes or quotes; anything else is ignored with a warning.
@@ -301,6 +370,18 @@ Run `gitbash --config-user` to create `.gitbashrc-user` for personal overrides i
301
370
  2. `.gitbashrc` - Repository settings (committed)
302
371
  3. `~/.gitbashrc` - Global settings
303
372
 
373
+ #### Updates
374
+
375
+ `gitbash --update` installs the latest release the same way gitbash was installed: with `npm install -g` (or `pnpm add -g`) for a global package, or by running the release's install script again for the same locations.
376
+
377
+ gitbash also checks for new releases on its own, at most once a day, in the background while a command runs, so commands never wait for the network. When a new version is known, the next command at a terminal asks (at most every other day) whether to update now, not now, or skip that version for good. It never asks in scripts or pipes.
378
+
379
+ To turn the checks off, answer "no" in `gitbash --config` or `--config-user`, set `GITBASH_NO_UPDATE_CHECKS="yes"` in any config file, or export `GITBASH_NO_UPDATE_CHECKS=1`. They are also off in CI (`CI` and similar variables) and when running from a git checkout. The check state is kept in `~/.local/state/gitbash/update-check` (`$XDG_STATE_HOME` if set).
380
+
381
+ #### Colors
382
+
383
+ gitbash supports [`NO_COLOR`](https://no-color.org): set it to any non-empty value (e.g. `export NO_COLOR=1`) to turn off all colors, including the help, messages, the git output in previews and `bat`. `delta` is not used then, and fzf uses its black-and-white theme. Colors are also left out when the output is not a terminal.
384
+
304
385
  ## License
305
386
 
306
387
  See [LICENSE](LICENSE) file for details.
package/bin/gitbash CHANGED
@@ -10,12 +10,20 @@ while [[ -L "$SOURCE" ]]; do
10
10
  done
11
11
  SCRIPT_DIR="$(cd -P "$(dirname "$SOURCE")/.." && pwd)"
12
12
  GITBASH_BIN="$SCRIPT_DIR/bin/gitbash"
13
+ # pnpm keeps each version in its own folder (node_modules/.pnpm/gitbash@X/node_modules/gitbash):
14
+ # run gitbash through the node_modules/gitbash link instead, which follows updates
15
+ if [[ "$SCRIPT_DIR" == */node_modules/.pnpm/gitbash@*/node_modules/gitbash &&
16
+ -x "${SCRIPT_DIR%%/.pnpm/*}/gitbash/bin/gitbash" ]]; then
17
+ GITBASH_BIN="${SCRIPT_DIR%%/.pnpm/*}/gitbash/bin/gitbash"
18
+ fi
13
19
  COMMANDS_DIR="$SCRIPT_DIR/commands"
14
20
  VERSION="$(grep -o '"version": *"[^"]*"' "$SCRIPT_DIR/package.json" | head -1 | cut -d'"' -f4)"
15
21
  export SCRIPT_DIR GITBASH_BIN VERSION
16
22
 
17
23
  # shellcheck source=../commands/_utils.sh
18
24
  source "$COMMANDS_DIR/_utils.sh"
25
+ # shellcheck source=../commands/_self_update.sh
26
+ source "$COMMANDS_DIR/_self_update.sh"
19
27
 
20
28
  # Available commands
21
29
  COMMANDS=(
@@ -26,6 +34,8 @@ COMMANDS=(
26
34
  "commits"
27
35
  "create"
28
36
  "pr"
37
+ "repo"
38
+ "reset-repo"
29
39
  "stale"
30
40
  "stash"
31
41
  "stashes"
@@ -50,7 +60,7 @@ is_command() {
50
60
  # key|type|question
51
61
  SETTINGS=(
52
62
  "GITBASH_CREATE_BRANCH_PREFIX|prefix|Branch prefix inserted between type and branch name (e.g. 'team' → feature/team/PROJ-123-fix-bug)"
53
- "GITBASH_CREATE_NO_ISSUE_PARSING|parsing|Parse Jira issue numbers into branch names? (yes/no)"
63
+ "GITBASH_CREATE_NO_ISSUE_PARSING|inverted|Parse Jira issue numbers into branch names? (yes/no)"
54
64
  "GITBASH_CREATE_ISSUE_PARSING_FALLBACK|text|Fallback issue prefix when no issue number is given"
55
65
  "GITBASH_CREATE_AUTO_PUSH|yesno|Push new branches to the remote right after 'create'? (yes/no)"
56
66
  "GITBASH_MERGE_COMMAND|command|Merge tool opened by 'update' on conflicts (not allowed in the committed .gitbashrc)"
@@ -58,8 +68,10 @@ SETTINGS=(
58
68
  "GITBASH_STALE_MONTHS|number|Stale remote branch threshold in months (used by 'stale')"
59
69
  "GITBASH_CLEANUP_DAYS|number|Stale local branch threshold in days (used by 'cleanup')"
60
70
  "GITBASH_PROTECTED_BRANCHES|text|Branches never offered for deletion (space-separated globs)"
71
+ "GITBASH_RESET_KEEP|text|Files kept by 'reset-repo' (space-separated .gitignore patterns, e.g. '.env .idea/')"
61
72
  "GITBASH_BASE_BRANCH|text|Base branch (empty = detect from the remote's HEAD, then main/master)"
62
73
  "GITBASH_REMOTE|text|Remote name"
74
+ "GITBASH_NO_UPDATE_CHECKS|inverted|Check for gitbash updates now and then, and offer to install them? (yes/no)"
63
75
  )
64
76
 
65
77
  # Default value of a setting
@@ -74,6 +86,7 @@ setting_default() {
74
86
  GITBASH_CLEANUP_DAYS) echo "7" ;;
75
87
  GITBASH_PROTECTED_BRANCHES) echo "main master develop release/*" ;;
76
88
  GITBASH_REMOTE) echo "origin" ;;
89
+ GITBASH_NO_UPDATE_CHECKS) echo "no" ;;
77
90
  *) echo "" ;;
78
91
  esac
79
92
  }
@@ -91,10 +104,10 @@ file_value() {
91
104
  }
92
105
 
93
106
  # Convert between the stored value and what the wizard shows.
94
- # GITBASH_CREATE_NO_ISSUE_PARSING is stored inverted.
107
+ # GITBASH_CREATE_NO_ISSUE_PARSING and GITBASH_NO_UPDATE_CHECKS are stored inverted.
95
108
  to_display() {
96
109
  local type="$1" value="$2"
97
- if [[ "$type" == "parsing" ]]; then
110
+ if [[ "$type" == "inverted" ]]; then
98
111
  [[ "$value" == "yes" ]] && echo "no" || echo "yes"
99
112
  else
100
113
  printf '%s' "$value"
@@ -109,7 +122,7 @@ to_stored() {
109
122
  return 1
110
123
  fi
111
124
  case "$type" in
112
- parsing)
125
+ inverted)
113
126
  case "$answer" in
114
127
  yes) echo "no" ;;
115
128
  no) echo "yes" ;;
@@ -183,7 +196,9 @@ configure_wizard() {
183
196
  for entry in "${SETTINGS[@]}"; do
184
197
  n=$((n + 1))
185
198
  IFS='|' read -r key type question <<< "$entry"
186
- [[ "$scope" == "local" && "$key" == "GITBASH_MERGE_COMMAND" ]] && continue
199
+ if [[ "$scope" == "local" ]]; then
200
+ [[ "$key" == "GITBASH_MERGE_COMMAND" || "$key" == "GITBASH_NO_UPDATE_CHECKS" ]] && continue
201
+ fi
187
202
 
188
203
  default=$(setting_default "$key")
189
204
  has_override=false
@@ -284,7 +299,17 @@ exclude_user_config() {
284
299
  print_info "Added .gitbashrc-user to $exclude"
285
300
  }
286
301
 
287
- # Report missing optional dependencies and offer to install them with Homebrew
302
+ # winget package id of a dependency
303
+ winget_id() {
304
+ case "$1" in
305
+ fzf) echo "junegunn.fzf" ;;
306
+ git-delta) echo "dandavison.delta" ;;
307
+ bat) echo "sharkdp.bat" ;;
308
+ esac
309
+ }
310
+
311
+ # Report missing optional dependencies and offer to install them with
312
+ # Homebrew, or winget on Windows
288
313
  check_dependencies() {
289
314
  local missing=() dep
290
315
  command -v fzf >/dev/null 2>&1 || missing+=("fzf")
@@ -301,18 +326,35 @@ check_dependencies() {
301
326
 
302
327
  echo "Missing optional dependencies: ${missing[*]}"
303
328
  echo " fzf (>= $GB_FZF_MIN_VERSION) - interactive menus, git-delta - diff highlighting, bat - file previews"
304
- if ! command -v brew >/dev/null 2>&1; then
305
- echo "Install them with your package manager, e.g.: sudo apt install ${missing[*]}"
329
+ local -a install
330
+ local manager
331
+ if gb_is_windows; then
332
+ manager="winget"
333
+ install=(winget install --exact --id)
334
+ else
335
+ manager="Homebrew"
336
+ install=(brew install)
337
+ fi
338
+ if ! command -v "${install[0]}" >/dev/null 2>&1; then
339
+ if gb_is_windows; then
340
+ echo "Install them with a package manager, e.g.: scoop install ${missing[*]/git-delta/delta}"
341
+ else
342
+ echo "Install them with your package manager, e.g.: sudo apt install ${missing[*]}"
343
+ fi
306
344
  return 0
307
345
  fi
308
- if gb_confirm "Install them with Homebrew?" y; then
346
+ local package
347
+ if gb_confirm "Install them with $manager?" y; then
309
348
  for dep in "${missing[@]}"; do
310
- if brew install "$dep"; then
349
+ package="$dep"
350
+ gb_is_windows && package=$(winget_id "$dep")
351
+ if "${install[@]}" "$package"; then
311
352
  print_success "$dep installed"
312
353
  else
313
354
  print_error "Failed to install $dep"
314
355
  fi
315
356
  done
357
+ gb_is_windows && print_info "Open a new terminal to pick up the installed programs."
316
358
  fi
317
359
  }
318
360
 
@@ -356,14 +398,38 @@ check_shell_integration() {
356
398
  # Help and shell integration
357
399
  # =============================================================================
358
400
 
359
- show_help() {
360
- cat << EOF
361
- gitbash $VERSION - Interactive git utilities for bash
401
+ # ASCII art logo with a color gradient, followed by the version.
402
+ # Plain text when stdout is not a terminal or NO_COLOR is set.
403
+ show_banner() {
404
+ local -a art=(
405
+ ' _ _ _ _ '
406
+ ' __ _(_) |_| |__ __ _ ___| |__ '
407
+ ' / _` | | __| '"'"'_ \ / _` / __| '"'"'_ \ '
408
+ ' | (_| | | |_| |_) | (_| \__ \ | | |'
409
+ ' \__, |_|\__|_.__/ \__,_|___/_| |_|'
410
+ ' |___/ '
411
+ )
412
+ local -a colors=(214 209 204 199 170 135)
413
+ local i
414
+ if _gb_color_ok 1; then
415
+ for i in "${!art[@]}"; do
416
+ printf '\033[1;38;5;%sm%s\033[0m\n' "${colors[$i]}" "${art[$i]}"
417
+ done
418
+ printf ' \033[1;38;5;135mv%s\033[0m \033[2m·\033[0m Interactive git utilities for bash\n' "$VERSION"
419
+ else
420
+ printf '%s\n' "${art[@]}"
421
+ printf ' v%s - Interactive git utilities for bash\n' "$VERSION"
422
+ fi
423
+ }
362
424
 
425
+ show_help() {
426
+ show_banner
427
+ echo
428
+ gb_help << EOF
363
429
  Usage:
364
430
  gitbash <command> [args...]
365
- gitbash --help | --version
366
- gitbash --init [--prefix=PREFIX]
431
+ gitbash --help | --version | --update
432
+ gitbash --init [--prefix=PREFIX] [--shell=pwsh]
367
433
  gitbash --config | --config-local | --config-user
368
434
 
369
435
  Commands:
@@ -371,9 +437,11 @@ Commands:
371
437
  cleanstash Delete stashes (multi-select)
372
438
  cleanup Find and delete leftover local branches
373
439
  commit Commit with optional push
374
- commits List recent commits with revert option
440
+ commits List the branch's commits with revert option
375
441
  create Create feature branch with Jira parsing
376
442
  pr Open PR in browser
443
+ repo Open the repository in browser
444
+ reset-repo Reset the branch like a fresh clone
377
445
  stale List stale remote branches
378
446
  stash Create named stash
379
447
  stashes Interactive stash menu
@@ -385,8 +453,10 @@ Commands:
385
453
  Options:
386
454
  -h, --help Show this help message
387
455
  -v, --version Show version number
456
+ --update Update gitbash to the latest release
388
457
  --init Print shell functions for calling commands directly
389
- (--prefix=gb- creates gb-commit, gb-switch, ...)
458
+ (--prefix=gb- creates gb-commit, gb-switch, ...;
459
+ --shell=pwsh prints PowerShell functions)
390
460
  --config Configure gitbash and save to ~/.gitbashrc
391
461
  --config-local Configure overrides for this repository (.gitbashrc, committed)
392
462
  --config-user Configure personal overrides for this repository (.gitbashrc-user)
@@ -399,6 +469,7 @@ Examples:
399
469
  Shell Integration:
400
470
  Add to your .zshrc or .bashrc:
401
471
  eval "\$(gitbash --init)"
472
+ PowerShell: see 'gitbash --init --shell=pwsh'
402
473
 
403
474
  This enables calling commands directly:
404
475
  commit fix bug -p
@@ -414,10 +485,12 @@ EOF
414
485
  # Print wrapper functions for the interactive shell. Commands still run in
415
486
  # their own bash process, so nothing leaks into the user's shell.
416
487
  show_init() {
417
- local prefix="" arg cmd bin_quoted
488
+ local prefix="" shell="sh" arg cmd bin_quoted
418
489
  for arg in "$@"; do
419
490
  case "$arg" in
420
491
  --prefix=*) prefix="${arg#--prefix=}" ;;
492
+ --shell=bash|--shell=zsh|--shell=sh) shell="sh" ;;
493
+ --shell=pwsh|--shell=powershell) shell="pwsh" ;;
421
494
  *) print_error "Unknown option for --init: $arg"; return 1 ;;
422
495
  esac
423
496
  done
@@ -425,6 +498,10 @@ show_init() {
425
498
  print_error "Invalid prefix '$prefix' (use letters, digits, '-' or '_')."
426
499
  return 1
427
500
  fi
501
+ if [[ "$shell" == "pwsh" ]]; then
502
+ show_init_pwsh "$prefix"
503
+ return
504
+ fi
428
505
  printf -v bin_quoted '%q' "$GITBASH_BIN"
429
506
  echo "# gitbash shell integration - add to your .zshrc or .bashrc:"
430
507
  echo "# eval \"\$(gitbash --init${prefix:+ --prefix=$prefix})\""
@@ -433,6 +510,50 @@ show_init() {
433
510
  done
434
511
  }
435
512
 
513
+ # Single-quoted PowerShell string
514
+ pwsh_quote() {
515
+ local q="'"
516
+ printf "'%s'" "${1//$q/$q$q}"
517
+ }
518
+
519
+ # The bash that PowerShell functions run gitbash with. On Windows, Git's
520
+ # bin\bash.exe: it puts git and the Unix tools on PATH, unlike usr\bin\bash.exe.
521
+ pwsh_bash() {
522
+ local bash_path git_root
523
+ bash_path=$(command -v bash)
524
+ if gb_is_windows && command -v cygpath >/dev/null 2>&1; then
525
+ git_root=$(cygpath -w /)
526
+ git_root="${git_root%\\}"
527
+ if [[ -f "$git_root\\bin\\bash.exe" ]]; then
528
+ printf '%s\n' "$git_root\\bin\\bash.exe"
529
+ else
530
+ cygpath -w "$bash_path"
531
+ fi
532
+ else
533
+ echo "$bash_path"
534
+ fi
535
+ }
536
+
537
+ # Functions for PowerShell ($PROFILE), running gitbash with bash
538
+ show_init_pwsh() {
539
+ local prefix="$1" bash_q bin_q cmd bin="$GITBASH_BIN"
540
+ gb_is_windows && command -v cygpath >/dev/null 2>&1 && bin=$(cygpath -m "$bin")
541
+ bash_q=$(pwsh_quote "$(pwsh_bash)")
542
+ bin_q=$(pwsh_quote "$bin")
543
+ echo "# gitbash shell integration for PowerShell - save it and dot-source it in your \$PROFILE:"
544
+ echo "# gitbash --init --shell=pwsh${prefix:+ --prefix=$prefix} > ~/gitbash.ps1"
545
+ echo "# . ~/gitbash.ps1"
546
+ echo "function gitbash { & $bash_q $bin_q @args }"
547
+ for cmd in "${COMMANDS[@]}"; do
548
+ # 'switch' is a PowerShell keyword: a function by that name can't be called
549
+ if [[ -z "$prefix" && "$cmd" == "switch" ]]; then
550
+ echo "# switch is a PowerShell keyword: use 'gitbash switch', or --prefix (e.g. gb-switch)"
551
+ continue
552
+ fi
553
+ echo "function ${prefix}${cmd} { & $bash_q $bin_q $cmd @args }"
554
+ done
555
+ }
556
+
436
557
  # =============================================================================
437
558
  # Main entry point
438
559
  # =============================================================================
@@ -445,6 +566,9 @@ main() {
445
566
  -v|--version)
446
567
  echo "gitbash $VERSION"
447
568
  ;;
569
+ --update)
570
+ gb_self_update
571
+ ;;
448
572
  --init)
449
573
  shift
450
574
  show_init "$@"
@@ -472,6 +596,9 @@ main() {
472
596
  return 1
473
597
  fi
474
598
  gb_load_config
599
+ gb_update_check "$cmd" "$@"
600
+ # Commands run gitbash again (e.g. pr runs commit): no update prompt in there
601
+ export GITBASH_NESTED=1
475
602
  # shellcheck source=/dev/null
476
603
  source "$COMMANDS_DIR/$cmd.sh"
477
604
  "$cmd" "$@"