param( [string]$RepoPath = (Split-Path $PSScriptRoot -Parent), [bool]$AutoStash = $true, [bool]$Push = $true, [ValidateSet('abort','leave')][string]$OnConflict = 'leave' ) function ExecGit { param([string[]]$ArgList, [bool]$IgnoreError = $false) Write-Host ("git " + ($ArgList -join ' ')) -ForegroundColor Cyan & git @ArgList $code = $LASTEXITCODE if (!$IgnoreError -and $code -ne 0) { throw ("Git command failed ({0}): git {1}" -f $code, ($ArgList -join ' ')) } return $code } try { if (!(Test-Path $RepoPath)) { throw ("RepoPath not found: {0}" -f $RepoPath) } Set-Location $RepoPath # Ensure git is available ExecGit @('--version') $true | Out-Null $currentBranch = (& git rev-parse --abbrev-ref HEAD).Trim() if ([string]::IsNullOrWhiteSpace($currentBranch)) { throw 'Cannot resolve current branch' } Write-Host ("Current branch: {0}" -f $currentBranch) -ForegroundColor Green # Check worktree state $statusPorcelain = (& git status --porcelain) $hasChanges = -not [string]::IsNullOrWhiteSpace(($statusPorcelain -join '')) $stashMade = $false if ($hasChanges -and $AutoStash) { Write-Host 'Worktree not clean, auto-stash' -ForegroundColor Yellow ExecGit @('stash','push','-u','-m','auto-stash before merge-main-framework') $stashMade = $true } elseif ($hasChanges -and -not $AutoStash) { throw 'Worktree has uncommitted changes; commit or enable -AutoStash' } # Fetch remotes ExecGit @('fetch','--all','--prune') # Ensure remote branch exists $remoteRef = (& git ls-remote --heads origin main-framework) if ([string]::IsNullOrWhiteSpace(($remoteRef -join ''))) { throw 'Remote origin/main-framework not found. Check remote and branch name.' } Write-Host ("Merging origin/main-framework -> {0}" -f $currentBranch) -ForegroundColor Green $mergeCode = ExecGit @('merge','--no-ff','origin/main-framework') $true # Detect conflicts $unmerged = (& git ls-files -u) $hasConflicts = -not [string]::IsNullOrWhiteSpace(($unmerged -join '')) if ($hasConflicts) { Write-Host ('Conflicts detected. Strategy: {0}' -f $OnConflict) -ForegroundColor Yellow if ($OnConflict -eq 'abort') { ExecGit @('merge','--abort') if ($stashMade) { Write-Host 'Restoring stash (stash pop)' -ForegroundColor Yellow ExecGit @('stash','pop') $true | Out-Null } throw 'Merge aborted. Please resolve conflicts manually and retry.' } else { Write-Host 'Leaving conflict state for manual resolution:' -ForegroundColor Yellow Write-Host '- Edit conflicted files and run: git add ' Write-Host '- Then conclude: git commit' if ($stashMade) { Write-Host 'Note: run stash pop after resolving' -ForegroundColor Yellow } exit 2 } } if ($mergeCode -eq 0) { Write-Host 'Merge completed.' -ForegroundColor Green } else { $st = (& git status) Write-Host $st } # Pop stash if any if ($stashMade) { Write-Host 'Restoring stash (stash pop)' -ForegroundColor Yellow ExecGit @('stash','pop') $true | Out-Null } # Push if requested if ($Push) { Write-Host 'Pushing to remote...' -ForegroundColor Green ExecGit @('push') Write-Host 'Push completed.' -ForegroundColor Green } Write-Host ("Done: origin/main-framework merged into {0}" -f $currentBranch) -ForegroundColor Green } catch { Write-Error $_ exit 1 }