gitbash 2.1.0 → 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,69 +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
10
12
 
11
13
  ```bash
12
- npm i -g gitbash && gitbash --config
14
+ npm i -g gitbash
15
+ brew install fzf git-delta bat
16
+ gitbash --config
13
17
  ```
14
18
 
15
- ### Via install script (no npm or node needed)
19
+ Shell integration (lets you type `commit` instead of `gitbash commit`):
16
20
 
17
21
  ```bash
18
- # curl
19
- curl -fsSL https://raw.githubusercontent.com/jaggli/gitbash/main/install.sh | sh
22
+ ## for bash
23
+ echo 'eval "$(gitbash --init)"' >> ~/.bashrc
24
+
25
+ ## for zsh
26
+ echo 'eval "$(gitbash --init)"' >> ~/.zshrc
27
+ ```
20
28
 
21
- # wget
22
- wget -qO- https://raw.githubusercontent.com/jaggli/gitbash/main/install.sh | sh
29
+ ### Linux
30
+
31
+ ```bash
32
+ npm i -g gitbash
33
+ sudo apt install fzf git-delta bat # Debian/Ubuntu, needs fzf >= 0.36
34
+ gitbash --config
23
35
  ```
24
36
 
25
- This downloads the latest GitHub release to `~/.local/share/gitbash` and links `~/.local/bin/gitbash`. Run `gitbash --update` (or the script again) to upgrade. Options are set as environment variables:
37
+ Shell integration:
26
38
 
27
39
  ```bash
28
- # Install a specific version
29
- curl -fsSL https://raw.githubusercontent.com/jaggli/gitbash/main/install.sh | GITBASH_VERSION=2.0.1 sh
40
+ ## for bash
41
+ echo 'eval "$(gitbash --init)"' >> ~/.bashrc
30
42
 
31
- # Custom locations (e.g. system-wide)
32
- curl -fsSL https://raw.githubusercontent.com/jaggli/gitbash/main/install.sh \
33
- | sudo GITBASH_INSTALL_DIR=/usr/local/share/gitbash GITBASH_BIN_DIR=/usr/local/bin sh
43
+ ## for zsh
44
+ echo 'eval "$(gitbash --init)"' >> ~/.zshrc
34
45
  ```
35
46
 
36
- To uninstall, remove `~/.local/share/gitbash` and `~/.local/bin/gitbash`.
47
+ ### Windows
37
48
 
38
- ### Options
49
+ In Git Bash (part of [Git for Windows](https://gitforwindows.org)); in WSL, follow the Linux steps:
39
50
 
40
51
  ```bash
41
- gitbash --help # Show help
42
- gitbash --version # Show version
43
- gitbash --update # Update to the latest release (npm or install script)
44
- gitbash --init # Print shell functions (see Shell integration)
45
- gitbash --config # Interactive configuration wizard
46
- gitbash --config-local # Configure overrides for the current repository (committed)
47
- gitbash --config-user # Configure personal overrides for the current repository
52
+ npm i -g gitbash
53
+ winget install junegunn.fzf dandavison.delta sharkdp.bat # needs fzf >= 0.54
54
+ gitbash --config
48
55
  ```
49
56
 
50
- ### Dependencies
57
+ Shell integration for Git Bash:
51
58
 
52
59
  ```bash
53
- # Required
54
- git >= 2.23, bash >= 3.2
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:
55
64
 
56
- # Optional (recommended)
57
- brew install fzf # Interactive menus and previews (fzf >= 0.36)
58
- brew install git-delta # Better diff highlighting
59
- brew install bat # File preview with syntax highlighting
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
60
75
  ```
61
76
 
62
- ### Shell integration
77
+ ### Without npm
63
78
 
64
- Add to your `.zshrc` or `.bashrc` to call the commands without the `gitbash` prefix:
79
+ Installation by script on machines without npm available
65
80
 
66
81
  ```bash
67
- eval "$(gitbash --init)" # commit, switch, status, ...
68
- eval "$(gitbash --init --prefix=gb-)" # gb-commit, gb-switch, ... (avoids shadowing e.g. /usr/bin/pr)
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
69
89
  ```
70
90
 
71
- 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"`.
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) |
72
106
 
73
107
  ## Commands
74
108
 
package/bin/gitbash CHANGED
@@ -299,7 +299,17 @@ exclude_user_config() {
299
299
  print_info "Added .gitbashrc-user to $exclude"
300
300
  }
301
301
 
302
- # 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
303
313
  check_dependencies() {
304
314
  local missing=() dep
305
315
  command -v fzf >/dev/null 2>&1 || missing+=("fzf")
@@ -316,18 +326,35 @@ check_dependencies() {
316
326
 
317
327
  echo "Missing optional dependencies: ${missing[*]}"
318
328
  echo " fzf (>= $GB_FZF_MIN_VERSION) - interactive menus, git-delta - diff highlighting, bat - file previews"
319
- if ! command -v brew >/dev/null 2>&1; then
320
- 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
321
344
  return 0
322
345
  fi
323
- if gb_confirm "Install them with Homebrew?" y; then
346
+ local package
347
+ if gb_confirm "Install them with $manager?" y; then
324
348
  for dep in "${missing[@]}"; do
325
- if brew install "$dep"; then
349
+ package="$dep"
350
+ gb_is_windows && package=$(winget_id "$dep")
351
+ if "${install[@]}" "$package"; then
326
352
  print_success "$dep installed"
327
353
  else
328
354
  print_error "Failed to install $dep"
329
355
  fi
330
356
  done
357
+ gb_is_windows && print_info "Open a new terminal to pick up the installed programs."
331
358
  fi
332
359
  }
333
360
 
@@ -402,7 +429,7 @@ show_help() {
402
429
  Usage:
403
430
  gitbash <command> [args...]
404
431
  gitbash --help | --version | --update
405
- gitbash --init [--prefix=PREFIX]
432
+ gitbash --init [--prefix=PREFIX] [--shell=pwsh]
406
433
  gitbash --config | --config-local | --config-user
407
434
 
408
435
  Commands:
@@ -428,7 +455,8 @@ Options:
428
455
  -v, --version Show version number
429
456
  --update Update gitbash to the latest release
430
457
  --init Print shell functions for calling commands directly
431
- (--prefix=gb- creates gb-commit, gb-switch, ...)
458
+ (--prefix=gb- creates gb-commit, gb-switch, ...;
459
+ --shell=pwsh prints PowerShell functions)
432
460
  --config Configure gitbash and save to ~/.gitbashrc
433
461
  --config-local Configure overrides for this repository (.gitbashrc, committed)
434
462
  --config-user Configure personal overrides for this repository (.gitbashrc-user)
@@ -441,6 +469,7 @@ Examples:
441
469
  Shell Integration:
442
470
  Add to your .zshrc or .bashrc:
443
471
  eval "\$(gitbash --init)"
472
+ PowerShell: see 'gitbash --init --shell=pwsh'
444
473
 
445
474
  This enables calling commands directly:
446
475
  commit fix bug -p
@@ -456,10 +485,12 @@ EOF
456
485
  # Print wrapper functions for the interactive shell. Commands still run in
457
486
  # their own bash process, so nothing leaks into the user's shell.
458
487
  show_init() {
459
- local prefix="" arg cmd bin_quoted
488
+ local prefix="" shell="sh" arg cmd bin_quoted
460
489
  for arg in "$@"; do
461
490
  case "$arg" in
462
491
  --prefix=*) prefix="${arg#--prefix=}" ;;
492
+ --shell=bash|--shell=zsh|--shell=sh) shell="sh" ;;
493
+ --shell=pwsh|--shell=powershell) shell="pwsh" ;;
463
494
  *) print_error "Unknown option for --init: $arg"; return 1 ;;
464
495
  esac
465
496
  done
@@ -467,6 +498,10 @@ show_init() {
467
498
  print_error "Invalid prefix '$prefix' (use letters, digits, '-' or '_')."
468
499
  return 1
469
500
  fi
501
+ if [[ "$shell" == "pwsh" ]]; then
502
+ show_init_pwsh "$prefix"
503
+ return
504
+ fi
470
505
  printf -v bin_quoted '%q' "$GITBASH_BIN"
471
506
  echo "# gitbash shell integration - add to your .zshrc or .bashrc:"
472
507
  echo "# eval \"\$(gitbash --init${prefix:+ --prefix=$prefix})\""
@@ -475,6 +510,50 @@ show_init() {
475
510
  done
476
511
  }
477
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
+
478
557
  # =============================================================================
479
558
  # Main entry point
480
559
  # =============================================================================
@@ -18,6 +18,10 @@ _gb_global_package_dir() {
18
18
  local root
19
19
  root=$("$1" root -g 2>/dev/null) || return 1
20
20
  [[ -n "$root" ]] || return 1
21
+ # Windows: C:\Users\...\npm\node_modules
22
+ if gb_is_windows && command -v cygpath >/dev/null 2>&1; then
23
+ root=$(cygpath -u "$root") || return 1
24
+ fi
21
25
  (cd -P "$root/gitbash" 2>/dev/null && pwd)
22
26
  }
23
27
 
@@ -9,7 +9,29 @@ if [[ -n "${_GB_UTILS_LOADED:-}" ]]; then
9
9
  fi
10
10
  _GB_UTILS_LOADED=1
11
11
 
12
- GB_FZF_MIN_VERSION="0.36.0"
12
+ # =============================================================================
13
+ # Platform
14
+ # =============================================================================
15
+
16
+ # Git Bash (MSYS2) or Cygwin on Windows
17
+ gb_is_windows() {
18
+ case "${OSTYPE:-}" in
19
+ msys*|cygwin*) return 0 ;;
20
+ esac
21
+ return 1
22
+ }
23
+
24
+ # Linux in WSL
25
+ _gb_is_wsl() {
26
+ [[ -n "${WSL_DISTRO_NAME:-}" || -n "${WSL_INTEROP:-}" ]]
27
+ }
28
+
29
+ # On Windows, fzf runs previews with bash and quotes {} for it since 0.54
30
+ if gb_is_windows; then
31
+ GB_FZF_MIN_VERSION="0.54.0"
32
+ else
33
+ GB_FZF_MIN_VERSION="0.36.0"
34
+ fi
13
35
 
14
36
  # =============================================================================
15
37
  # Output
@@ -286,7 +308,11 @@ _gb_version_ge() {
286
308
  # Check that fzf is installed and recent enough
287
309
  require_fzf() {
288
310
  if ! command -v fzf >/dev/null 2>&1; then
289
- print_error "fzf is not installed. Install it with 'brew install fzf' (macOS) or 'sudo apt install fzf' (Debian/Ubuntu)."
311
+ if gb_is_windows; then
312
+ print_error "fzf is not installed. Install it with 'winget install junegunn.fzf'."
313
+ else
314
+ print_error "fzf is not installed. Install it with 'brew install fzf' (macOS) or 'sudo apt install fzf' (Debian/Ubuntu)."
315
+ fi
290
316
  return 1
291
317
  fi
292
318
  local version
@@ -632,7 +658,14 @@ gb_web_url() {
632
658
  # Open a URL in the browser, or print it if no opener is available
633
659
  gb_open_url() {
634
660
  local url="$1"
635
- if command -v open >/dev/null 2>&1 && [[ "$(uname -s)" == "Darwin" ]]; then
661
+ if gb_is_windows && command -v rundll32 >/dev/null 2>&1; then
662
+ # Not cmd's start: it would need & and ^ in the URL escaped
663
+ rundll32 url.dll,FileProtocolHandler "$url"
664
+ elif _gb_is_wsl && command -v wslview >/dev/null 2>&1; then
665
+ wslview "$url"
666
+ elif _gb_is_wsl && command -v rundll32.exe >/dev/null 2>&1; then
667
+ rundll32.exe url.dll,FileProtocolHandler "$url"
668
+ elif command -v open >/dev/null 2>&1 && [[ "$(uname -s)" == "Darwin" ]]; then
636
669
  open "$url"
637
670
  elif command -v xdg-open >/dev/null 2>&1; then
638
671
  xdg-open "$url" >/dev/null 2>&1
package/commands/pr.sh CHANGED
@@ -59,7 +59,7 @@ Behavior:
59
59
  Bitbucket <repo>/pull-requests/new?source=<branch>
60
60
  Azure DevOps <repo>/pullrequestcreate?sourceRef=<branch>
61
61
  - Works with SSH and HTTPS remotes; credentials in the remote URL are never used
62
- - Opens the browser with 'open' (macOS) or 'xdg-open' (Linux), otherwise prints the URL
62
+ - Opens the browser (macOS, Linux, WSL, Git Bash on Windows), otherwise prints the URL
63
63
 
64
64
  Examples:
65
65
  $ pr
package/commands/repo.sh CHANGED
@@ -31,7 +31,7 @@ Behavior:
31
31
  - Otherwise opens the URL derived from the remote
32
32
  (GitHub, GitHub Enterprise, GitLab, Bitbucket, Azure DevOps)
33
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
34
+ - Opens the browser (macOS, Linux, WSL, Git Bash on Windows), otherwise prints the URL
35
35
 
36
36
  Examples:
37
37
  $ repo
@@ -125,7 +125,7 @@ shellcheck -x bin/gitbash commands/*.sh
125
125
 
126
126
  Tests live in `test/*.bats`. Each test gets its own temporary repository with a local bare remote (`test/helpers/setup.bash`). fzf is replaced by a stub that records its arguments and answers from a plan (`test/helpers/bin/fzf`); `test/fzf_real.bats` drives the real fzf in a pseudo-terminal. Add a test for every bug fix.
127
127
 
128
- CI runs shellcheck and the tests on Ubuntu (bash 5) and macOS (bash 3.2 and 5).
128
+ CI runs shellcheck and the tests on Ubuntu (bash 5), macOS (bash 3.2 and 5) and Windows (Git Bash). Scripts must keep LF line endings (`.gitattributes` enforces it).
129
129
 
130
130
  ### Code style:
131
131
  - Follow existing bash script conventions; scripts must work with bash 3.2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gitbash",
3
- "version": "2.1.0",
3
+ "version": "2.2.0",
4
4
  "description": "Opinionated git utilities for bash with fzf-powered menus",
5
5
  "author": "jaggli",
6
6
  "license": "MIT",
@@ -35,7 +35,8 @@
35
35
  ],
36
36
  "os": [
37
37
  "darwin",
38
- "linux"
38
+ "linux",
39
+ "win32"
39
40
  ],
40
41
  "engines": {
41
42
  "node": ">=14"