Skip to content
Latchkey

How to Handle Shell Differences (bash vs pwsh) in a Matrix

Windows runners default to PowerShell while Linux and macOS default to bash, so set shell: bash for a script that must run the same everywhere.

The default shell changes per OS, which breaks scripts written for one interpreter. Set shell: on the step (or defaults.run.shell) to force a consistent interpreter.

Steps

  • Set shell: bash on a step to use bash on all three runners (Git Bash on Windows).
  • Set shell: pwsh when you want PowerShell Core everywhere.
  • Use defaults.run.shell to apply one shell to the whole job.

Workflow

.github/workflows/ci.yml
jobs:
  test:
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest]
    runs-on: ${{ matrix.os }}
    defaults:
      run:
        shell: bash
    steps:
      - uses: actions/checkout@v4
      - run: |
          echo "Same bash on every OS"
          ./scripts/build.sh

Gotchas

  • bash on Windows is Git Bash, so Unix paths work but Windows-only tools may need a native path.
  • pwsh (PowerShell Core) differs from the legacy powershell shell; pick one and stay consistent.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →