plugins/ado-master/skills/ado-windows-git-bash-compatibility/SKILL.md
Windows and Git Bash compatibility for Azure Pipelines. PROACTIVELY activate for: (1) pipelines that pass on Linux but fail on Windows agents, (2) path conversion issues in pipeline scripts (MSYS, MINGW), (3) shell detection (bash@3, pwsh@2, powershell@2 task selection), (4) MSYS_NO_PATHCONV and MSYS2_ARG_CONV_EXCL workarounds, (5) Windows self-hosted agent configuration, (6) cross-platform script patterns, (7) line-ending issues (CRLF vs LF) in checked-in scripts, (8) Docker on Windows agents, (9) UNC and long-path limitations. Provides: shell-task selection matrix, path-conversion env-var recipes, line-ending fixes, and a Windows-specific pipeline troubleshooting playbook.
npx skillsauth add JosiahSiegel/claude-plugin-marketplace ado-windows-git-bash-compatibilityInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Azure Pipelines frequently run on Windows agents, and teams often use Git Bash for scripting. This creates path conversion and shell compatibility challenges that can cause pipeline failures. This guide provides comprehensive solutions for Windows/Git Bash integration in Azure DevOps pipelines.
Microsoft's Official Position:
Git Version Management:
System.PreferGitFromPath=trueGit Bash Location on Windows Agents:
C:\Program Files (x86)\Git\usr\bin\bash.exe
C:\Program Files\Git\usr\bin\bash.exe
When using Bash tasks on Windows agents, Azure DevOps variables return Windows-style paths, but Git Bash (MINGW) performs automatic path conversion that can cause issues.
# ❌ FAILS - Backslashes treated as escape characters
- bash: |
cd $(System.DefaultWorkingDirectory) # d:\a\s\1 becomes d:as1
Solution:
# ✅ CORRECT - Use forward slashes or variable properly
- bash: |
cd "$BUILD_SOURCESDIRECTORY"
# Or use PWD variable which is already set correctly
echo "Working in: $PWD"
# ❌ FAILS - MINGW converts /d /s style arguments
- bash: |
my-tool /d $(Build.SourcesDirectory)
Solution:
# ✅ CORRECT - Use double slashes or environment variable
- bash: |
export MSYS_NO_PATHCONV=1
my-tool /d $(Build.SourcesDirectory)
unset MSYS_NO_PATHCONV
# ❌ FAILS - MINGW converts colon-separated Windows paths
- bash: |
export PATH="/usr/bin:$(Agent.ToolsDirectory)"
Solution:
# ✅ CORRECT - Use semicolon for Windows or convert properly
- bash: |
# For Windows-style paths
export PATH="/usr/bin;$(Agent.ToolsDirectory)"
- bash: |
case "$OSTYPE" in
linux-gnu*)
echo "Running on Linux agent"
BUILD_PATH="$(Build.SourcesDirectory)"
;;
darwin*)
echo "Running on macOS agent"
BUILD_PATH="$(Build.SourcesDirectory)"
;;
msys*|mingw*|cygwin*)
echo "Running on Windows agent with Git Bash"
# Windows paths already work in MINGW, but may need conversion
BUILD_PATH="$(Build.SourcesDirectory)"
export MSYS_NO_PATHCONV=1
;;
*)
echo "Unknown OS: $OSTYPE"
BUILD_PATH="$(Build.SourcesDirectory)"
;;
esac
echo "Build path: $BUILD_PATH"
cd "$BUILD_PATH"
displayName: 'Cross-platform path handling'
- bash: |
OS_TYPE=$(uname -s)
case "$OS_TYPE" in
Darwin*)
echo "macOS agent detected"
;;
Linux*)
echo "Linux agent detected"
# Check if WSL
if grep -qi microsoft /proc/version 2>/dev/null; then
echo "Running in WSL"
fi
;;
MINGW64*|MINGW32*)
echo "Git Bash on Windows detected"
export MSYS_NO_PATHCONV=1
;;
CYGWIN*)
echo "Cygwin on Windows detected"
;;
MSYS_NT*)
echo "MSYS on Windows detected"
export MSYS_NO_PATHCONV=1
;;
*)
echo "Unknown OS: $OS_TYPE"
;;
esac
displayName: 'Detect shell environment'
- bash: |
if [ "$(Agent.OS)" = "Windows_NT" ]; then
echo "Windows agent - applying MINGW path handling"
export MSYS_NO_PATHCONV=1
elif [ "$(Agent.OS)" = "Linux" ]; then
echo "Linux agent"
elif [ "$(Agent.OS)" = "Darwin" ]; then
echo "macOS agent"
fi
displayName: 'Agent-specific configuration'
Disables ALL automatic path conversion in MINGW/Git Bash:
- bash: |
# Disable path conversion for this script
export MSYS_NO_PATHCONV=1
# Now Windows paths work as-is
dotnet build /p:Configuration=Release
docker run -v "$(Build.SourcesDirectory):/workspace" myimage
# Optionally re-enable
unset MSYS_NO_PATHCONV
displayName: 'Build with path conversion disabled'
Exclude specific argument patterns from conversion:
- bash: |
# Exclude specific prefixes from conversion
export MSYS2_ARG_CONV_EXCL="--config=;/p:"
dotnet build /p:Configuration=Release --config=$(Build.SourcesDirectory)/app.config
displayName: 'Selective path conversion'
Convert between Windows and Unix paths explicitly:
- bash: |
# Convert Windows path to Unix
UNIX_PATH=$(cygpath -u "$(Build.SourcesDirectory)")
echo "Unix path: $UNIX_PATH"
# Convert Unix path to Windows
WINDOWS_PATH=$(cygpath -w "$PWD")
echo "Windows path: $WINDOWS_PATH"
# Mixed format (forward slashes with drive letter)
MIXED_PATH=$(cygpath -m "$(Build.SourcesDirectory)")
echo "Mixed path: $MIXED_PATH"
displayName: 'Path conversion examples'
jobs:
- job: CrossPlatformBuild
strategy:
matrix:
Linux:
imageName: 'ubuntu-24.04'
osType: 'Linux'
Windows:
imageName: 'windows-2025'
osType: 'Windows_NT'
macOS:
imageName: 'macOS-15'
osType: 'Darwin'
pool:
vmImage: $(imageName)
steps:
# Windows-specific setup
- bash: |
export MSYS_NO_PATHCONV=1
echo "Windows Git Bash configuration applied"
condition: eq(variables['Agent.OS'], 'Windows_NT')
displayName: 'Windows Git Bash setup'
# Cross-platform build
- bash: |
echo "Building on: $(Agent.OS)"
cd "$(Build.SourcesDirectory)"
npm install
npm run build
displayName: 'Cross-platform build'
# File: templates/cross-platform-script.yml
parameters:
- name: script
type: string
steps:
- bash: |
# Auto-detect Windows and apply MSYS configuration
if [ "$(Agent.OS)" = "Windows_NT" ]; then
export MSYS_NO_PATHCONV=1
fi
# Run provided script
${{ parameters.script }}
displayName: 'Cross-platform script execution'
# Usage in main pipeline:
steps:
- template: templates/cross-platform-script.yml
parameters:
script: |
dotnet build /p:Configuration=Release
dotnet test --no-build
- pwsh: |
Write-Host "Building on Windows with PowerShell"
dotnet build /p:Configuration=Release
condition: eq(variables['Agent.OS'], 'Windows_NT')
displayName: 'Windows build (PowerShell)'
- bash: |
echo "Building on Unix with Bash"
dotnet build -p:Configuration=Release
condition: ne(variables['Agent.OS'], 'Windows_NT')
displayName: 'Unix build (Bash)'
# ❌ FAILS - Windows paths in bash arguments
- bash: |
az pipelines run --id 123 --variables sourceDir=$(Build.SourcesDirectory)
Solution:
# ✅ CORRECT - Use MSYS_NO_PATHCONV or proper quoting
- bash: |
export MSYS_NO_PATHCONV=1
az pipelines run --id 123 --variables sourceDir="$(Build.SourcesDirectory)"
- bash: |
# Configure Git to handle Windows paths correctly
git config --global core.autocrlf true
git config --global core.safecrlf false
# Clone with proper path handling
export MSYS_NO_PATHCONV=1
az repos pr create \
--repository myrepo \
--source-branch feature/new \
--target-branch main
displayName: 'Git operations on Windows agent'
condition: eq(variables['Agent.OS'], 'Windows_NT')
- bash: |
# Recommended Git configuration for Windows agents
git config --global core.autocrlf true
git config --global core.longpaths true
git config --global core.symlinks false
# Show configuration
git config --list | grep core
displayName: 'Configure Git for Windows'
condition: eq(variables['Agent.OS'], 'Windows_NT')
# Use system Git instead of agent-bundled Git
variables:
System.PreferGitFromPath: true
steps:
- bash: |
git --version
which git
displayName: 'Check Git version'
For self-hosted Windows agents, create .env file in agent root:
# File: agent/.env
System.PreferGitFromPath=true
MSYS_NO_PATHCONV=1
- bash: |
echo "=== Environment Diagnostics ==="
echo "Agent.OS: $(Agent.OS)"
echo "Agent.OSArchitecture: $(Agent.OSArchitecture)"
echo "System.DefaultWorkingDirectory: $(System.DefaultWorkingDirectory)"
echo "Build.SourcesDirectory: $(Build.SourcesDirectory)"
echo ""
echo "=== Shell Detection ==="
echo "OSTYPE: $OSTYPE"
echo "MSYSTEM: $MSYSTEM"
uname -a
echo ""
echo "=== Path Information ==="
echo "PWD: $PWD"
echo "HOME: $HOME"
echo "PATH: $PATH"
echo ""
echo "=== Git Configuration ==="
git --version
which git
git config --list | grep core
echo ""
echo "=== Path Conversion Test ==="
echo "Windows-style: $(Build.SourcesDirectory)"
if command -v cygpath &> /dev/null; then
echo "Unix-style: $(cygpath -u "$(Build.SourcesDirectory)")"
echo "Mixed-style: $(cygpath -m "$(Build.SourcesDirectory)")"
fi
displayName: 'Windows agent diagnostics'
condition: eq(variables['Agent.OS'], 'Windows_NT')
# Error: bash: line 1: d:as1: No such file or directory
# ❌ Problem: Backslashes removed
- bash: cd $(System.DefaultWorkingDirectory)
# ✅ Solution: Quote the variable
- bash: cd "$(System.DefaultWorkingDirectory)"
# Error: Invalid switch - "/d"
# ❌ Problem: MINGW converts /d to Windows path
- bash: dotnet test /d:SonarQubeAnalysisPath=.
# ✅ Solution: Disable path conversion
- bash: |
export MSYS_NO_PATHCONV=1
dotnet test /d:SonarQubeAnalysisPath=.
# Error: Access to path 'C:\Program' is denied
# ❌ Problem: Unquoted path with spaces
- bash: my-tool $(Agent.ToolsDirectory)/mytool
# ✅ Solution: Always quote paths
- bash: my-tool "$(Agent.ToolsDirectory)/mytool"
"$(Build.SourcesDirectory)"$(Agent.OS) or unamecd $(Build.SourcesDirectory)Use this at the start of complex cross-platform scripts:
- bash: |
#!/bin/bash
set -euo pipefail
# Detect platform and configure
if [ "$(Agent.OS)" = "Windows_NT" ]; then
echo "Windows agent detected"
export MSYS_NO_PATHCONV=1
PATH_SEP=";"
else
echo "Unix-like agent detected"
PATH_SEP=":"
fi
# Your script logic here
echo "Build directory: $(Build.SourcesDirectory)"
cd "$(Build.SourcesDirectory)"
# Platform-agnostic operations
npm install
npm run build
displayName: 'Cross-platform build script'
| Scenario | Solution |
|----------|----------|
| Bash script on Windows | Use export MSYS_NO_PATHCONV=1 |
| Detect Windows agent | Check $(Agent.OS) = Windows_NT |
| Detect Git Bash | Check uname -s starts with MINGW |
| Convert Windows → Unix | cygpath -u "C:\path" |
| Convert Unix → Windows | cygpath -w "/c/path" |
| Quote paths with spaces | Always use "$(variable)" |
| Disable conversion for arg | export MSYS2_ARG_CONV_EXCL="pattern" |
| Check Git version | git --version && which git |
| Use system Git | Set System.PreferGitFromPath: true |
| Test path handling | Run diagnostic script above |
When in doubt, use MSYS_NO_PATHCONV=1 for Windows agents running Bash tasks.
development
This skill should be used when the user asks to train, debug, scale, or improve ML models. PROACTIVELY activate for: (1) PyTorch, TensorFlow/Keras, JAX, Flax, Hugging Face Trainer/Accelerate training loops, (2) distributed training, DDP/FSDP/DeepSpeed, TPU/GPU setup, (3) mixed precision AMP/bf16, gradient accumulation, checkpointing, seeding, (4) overfitting, imbalance, loss functions, regularization, LR schedules, warmup, (5) memory optimization, gradient checkpointing, offloading, quantization-aware training. Provides: reproducible training best practices across deep learning and classical ML.
development
This skill should be used when the user asks to productionize, track, version, govern, monitor, or automate ML systems. PROACTIVELY activate for: (1) MLflow, Weights & Biases, Neptune, Comet, ClearML experiment tracking, (2) model registry, model versioning, artifact lineage, reproducibility, (3) Kubeflow, SageMaker Pipelines, Vertex AI Pipelines, Azure ML pipelines, Databricks workflows, (4) CI/CD, continuous training/evaluation, A/B tests, canary/shadow deployments, (5) drift detection, model monitoring, data validation, responsible AI governance. Provides: end-to-end MLOps architecture and operational safeguards.
development
This skill should be used when the user asks to optimize, export, serve, compress, or accelerate ML inference. PROACTIVELY activate for: (1) latency, throughput, p95/p99, batching, concurrency, KV cache, memory, or cost issues, (2) quantization INT8/INT4, GPTQ, AWQ, bitsandbytes, pruning, sparsity, distillation, (3) ONNX export, ONNX Runtime, TensorRT, TorchScript, torch.compile, XLA, OpenVINO, Core ML, TFLite, (4) Triton, TorchServe, TF Serving, BentoML, Seldon, KServe configuration, (5) edge deployment, CPU/GPU/TPU/Inferentia serving. Provides: hardware-aware inference optimization and safe benchmarking.
testing
This skill should be used when the user asks to tune hyperparameters, run sweeps, optimize search spaces, or use AutoML. PROACTIVELY activate for: (1) Optuna, Ray Tune, FLAML, AutoGluon, Hyperopt, Nevergrad, KerasTuner, W&B sweeps, (2) grid search, random search, Bayesian optimization, TPE, Gaussian processes, evolutionary search, (3) ASHA, Hyperband, successive halving, multi-fidelity optimization, population-based training, (4) learning-rate finder, batch-size search, early stopping, pruning, (5) reproducible sweep design and experiment analysis. Provides: budget-aware hyperparameter search strategy.