Windows and Git Bash path handling for SSDT, SqlPackage, and DACPAC files with shell detection
MANDATORY: Always Use Backslashes on Windows for File Paths
When using Edit or Write tools on Windows, you MUST use backslashes (\) in file paths, NOT forward slashes (/).
Examples:
D:/repos/project/file.tsxD:\repos\project\file.tsxThis applies to:
NEVER create new documentation files unless explicitly requested by the user.
SQL Server development is Windows-heavy, and many developers use Git Bash (MINGW/MSYS2) as their preferred shell on Windows. This creates unique path conversion challenges when working with Windows-native tools like SqlPackage, MSBuild, and Visual Studio that expect Windows-style paths.
This skill provides comprehensive guidance on handling path conversion issues, shell detection, and best practices for SSDT workflows on Windows with Git Bash.
Git Bash automatically converts POSIX-style paths to Windows paths, but this can cause issues with command-line arguments:
Automatic Conversions:
/foo → C:/Program Files/Git/usr/foo/foo:/bar → C:\msys64\foo;C:\msys64\bar--dir=/foo → --dir=C:/msys64/fooProblematic for SqlPackage:
# Git Bash converts /Action to a path!
sqlpackage /Action:Publish /SourceFile:MyDB.dacpac
# Becomes: sqlpackage C:/Program Files/Git/usr/Action:Publish ...
✓ Leading forward slash (/) in arguments
✓ Colon-separated path lists
✓ Arguments after - or , with path components
✓ Arguments containing = (variable assignments)
✓ Drive specifiers (C:)
✓ Arguments with ; (already Windows format)
✓ Arguments starting with // (Windows switches)
Disable path conversion for specific commands:
# Temporarily disable path conversion
MSYS_NO_PATHCONV=1 sqlpackage /Action:Publish \
/SourceFile:"MyDatabase.dacpac" \
/TargetServerName:"localhost" \
/TargetDatabaseName:"MyDB"
# Works for all SqlPackage actions
MSYS_NO_PATHCONV=1 sqlpackage /Action:Extract \
/SourceConnectionString:"Server=localhost;Database=MyDB;Integrated Security=True;" \
/TargetFile:"MyDB_backup.dacpac"
Important Notes:
0, false, or empty still disables conversionenv -u MSYS_NO_PATHCONVUse double slashes for SqlPackage parameters:
# Works in Git Bash and CMD
sqlpackage //Action:Publish \
//SourceFile:MyDatabase.dacpac \
//TargetServerName:localhost \
//TargetDatabaseName:MyDB
# Extract with double slashes
sqlpackage //Action:Extract \
//SourceConnectionString:"Server=localhost;Database=MyDB;Integrated Security=True;" \
//TargetFile:output.dacpac
Advantages:
Always quote paths with backslashes:
# Quoted Windows paths work in Git Bash
MSYS_NO_PATHCONV=1 sqlpackage /Action:Publish \
/SourceFile:"D:\Projects\MyDB\bin\Release\MyDB.dacpac" \
/TargetConnectionString:"Server=localhost;Database=MyDB;Integrated Security=True;"
# Or with forward slashes (Windows accepts both)
MSYS_NO_PATHCONV=1 sqlpackage /Action:Publish \
/SourceFile:"D:/Projects/MyDB/bin/Release/MyDB.dacpac" \
/TargetConnectionString:"Server=localhost;Database=MyDB;Integrated Security=True;"
For Windows-native tools, consider using native shells:
# PowerShell (recommended for Windows SSDT workflows)
sqlpackage /Action:Publish `
/SourceFile:"MyDatabase.dacpac" `
/TargetServerName:"localhost" `
/TargetDatabaseName:"MyDB"
:: CMD
sqlpackage /Action:Publish ^
/SourceFile:"MyDatabase.dacpac" ^
/TargetServerName:"localhost" ^
/TargetDatabaseName:"MyDB"
#!/bin/bash
# Method 1: Check $OSTYPE
case "$OSTYPE" in
msys*) # MSYS/Git Bash/MinGW
export MSYS_NO_PATHCONV=1
SQLPACKAGE_ARGS="/Action:Publish /SourceFile:MyDB.dacpac"
;;
cygwin*) # Cygwin
export MSYS_NO_PATHCONV=1
SQLPACKAGE_ARGS="/Action:Publish /SourceFile:MyDB.dacpac"
;;
linux-gnu*) # Linux
SQLPACKAGE_ARGS="/Action:Publish /SourceFile:MyDB.dacpac"
;;
darwin*) # macOS
SQLPACKAGE_ARGS="/Action:Publish /SourceFile:MyDB.dacpac"
;;
esac
sqlpackage $SQLPACKAGE_ARGS
# Method 2: Check uname -s (most portable)
case "$(uname -s)" in
MINGW64*|MINGW32*)
# Git Bash
export MSYS_NO_PATHCONV=1
echo "Git Bash detected - path conversion disabled"
;;
MSYS_NT*)
# MSYS
export MSYS_NO_PATHCONV=1
echo "MSYS detected - path conversion disabled"
;;
CYGWIN*)
# Cygwin
export MSYS_NO_PATHCONV=1
echo "Cygwin detected - path conversion disabled"
;;
Linux*)
# Linux or WSL
echo "Linux detected"
;;
Darwin*)
# macOS
echo "macOS detected"
;;
esac
# Method 3: Check $MSYSTEM (Git Bash specific)
if [ -n "$MSYSTEM" ]; then
# Running in Git Bash/MSYS2
export MSYS_NO_PATHCONV=1
echo "MSYS environment detected: $MSYSTEM"
case "$MSYSTEM" in
MINGW64) echo "64-bit native Windows environment" ;;
MINGW32) echo "32-bit native Windows environment" ;;
MSYS) echo "POSIX-compliant environment" ;;
esac
fi
#!/bin/bash
# build-and-deploy.sh - Cross-platform SSDT build script
set -e # Exit on error
# Detect shell and set path conversion
if [ -n "$MSYSTEM" ]; then
echo "Git Bash/MSYS2 detected - disabling path conversion"
export MSYS_NO_PATHCONV=1
fi
# Variables
PROJECT_NAME="MyDatabase"
BUILD_CONFIG="Release"
DACPAC_PATH="bin/${BUILD_CONFIG}/${PROJECT_NAME}.dacpac"
TARGET_SERVER="${SQL_SERVER:-localhost}"
TARGET_DB="${SQL_DATABASE:-MyDB}"
# Build
echo "Building ${PROJECT_NAME}..."
dotnet build "${PROJECT_NAME}.sqlproj" -c "$BUILD_CONFIG"
# Verify DACPAC exists
if [ ! -f "$DACPAC_PATH" ]; then
echo "ERROR: DACPAC not found at $DACPAC_PATH"
exit 1
fi
echo "DACPAC built successfully: $DACPAC_PATH"
# Deploy
echo "Deploying to ${TARGET_SERVER}/${TARGET_DB}..."
# Use double-slash method for maximum compatibility
sqlpackage //Action:Publish \
//SourceFile:"$DACPAC_PATH" \
//TargetServerName:"$TARGET_SERVER" \
//TargetDatabaseName:"$TARGET_DB" \
//p:BlockOnPossibleDataLoss=False
echo "Deployment complete!"
Problem:
# Git Bash mangles the path
sqlpackage /Action:Publish /SourceFile:./bin/Release/MyDB.dacpac
# Error: Cannot find file
Solution:
# Use MSYS_NO_PATHCONV
MSYS_NO_PATHCONV=1 sqlpackage /Action:Publish \
/SourceFile:"./bin/Release/MyDB.dacpac"
# OR use absolute Windows path
MSYS_NO_PATHCONV=1 sqlpackage /Action:Publish \
/SourceFile:"D:/Projects/MyDB/bin/Release/MyDB.dacpac"
# OR use double slashes
sqlpackage //Action:Publish //SourceFile:./bin/Release/MyDB.dacpac
Problem:
# Path with spaces causes issues
dotnet build "D:/Program Files/MyProject/Database.sqlproj"
# Works in Git Bash (dotnet handles paths correctly)
# But MSBuild paths may fail
msbuild "D:/Program Files/MyProject/Database.sqlproj"
# May fail if not quoted properly
Solution:
# Always quote paths with spaces
dotnet build "D:/Program Files/MyProject/Database.sqlproj"
# Use backslashes for MSBuild on Windows
msbuild "D:\Program Files\MyProject\Database.sqlproj"
# Or use 8.3 short names (no spaces)
msbuild "D:/PROGRA~1/MyProject/Database.sqlproj"
Problem:
# Publish profile not found
sqlpackage /Action:Publish \
/SourceFile:MyDB.dacpac \
/Profile:./Profiles/Production.publish.xml
Solution:
# Use MSYS_NO_PATHCONV with quoted paths
MSYS_NO_PATHCONV=1 sqlpackage /Action:Publish \
/SourceFile:"MyDB.dacpac" \
/Profile:"./Profiles/Production.publish.xml"
# Or absolute Windows path
MSYS_NO_PATHCONV=1 sqlpackage /Action:Publish \
/SourceFile:"D:/Projects/MyDB.dacpac" \
/Profile:"D:/Projects/Profiles/Production.publish.xml"
Problem:
# File paths in connection strings
/SourceConnectionString:"Server=localhost;Database=MyDB;Integrated Security=True;AttachDbFilename=D:/Data/MyDB.mdf"
# Path gets mangled
Solution:
# Quote entire connection string
MSYS_NO_PATHCONV=1 sqlpackage /Action:Extract \
/SourceConnectionString:"Server=localhost;Database=MyDB;Integrated Security=True;AttachDbFilename=D:\Data\MyDB.mdf" \
/TargetFile:"output.dacpac"
# Or use double backslashes in connection string
/SourceConnectionString:"Server=localhost;Database=MyDB;Integrated Security=True;AttachDbFilename=D:\\Data\\MyDB.mdf"