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: bashon a step to use bash on all three runners (Git Bash on Windows). - Set
shell: pwshwhen you want PowerShell Core everywhere. - Use
defaults.run.shellto 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.shGotchas
- 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
powershellshell; pick one and stay consistent.
Related guides
How to Run Steps Conditionally Per OS in GitHub ActionsRun a step only on a specific operating system in a GitHub Actions matrix with if: runner.os == Windows, so p…
How to Handle Windows Path and Line-Ending Gotchas in CIAvoid the two classic Windows CI failures: backslash path separators and CRLF line endings, by configuring co…