Public/Save-GitWorktree.ps1

<#
.SYNOPSIS
    Stages all changes, commits, pushes, and then prunes the worktree.
.DESCRIPTION
    Runs `git add -A`, commits with -Message, pushes the branch to origin,
    then changes location to the bare repo root and prunes the worktree entry.
    Use -NoPush to skip pushing (local commit only).
    Use -NoPrune to keep the worktree after pushing.
.EXAMPLE
    Save-GitWorktree -Message "Fix login bug"
.EXAMPLE
    Save-GitWorktree -Message "WIP" -NoPush -NoPrune
#>

function Save-GitWorktree {
    [CmdletBinding(SupportsShouldProcess)]
    param(
        [Parameter(Mandatory, Position = 0)]
        [ValidateNotNullOrEmpty()]
        [string] $Message,

        [Parameter()]
        [switch] $NoPush,

        [Parameter()]
        [switch] $NoPrune,

        [Parameter()]
        [string] $Path = (Get-Location).Path
    )

    $Path = (Resolve-Path $Path -ErrorAction Stop).Path
    $root = Get-GitRoot -Path $Path

    # Confirm this is actually a worktree (not the bare repo itself)
    $worktrees = Get-WorktreeList -RepoPath $root
    $entry     = $worktrees | Where-Object { $_.Path -eq $Path -and -not $_.IsBare }
    if (-not $entry) {
        throw "'$Path' is not a non-bare worktree. Navigate into a worktree first."
    }

    $branch = $entry.Branch
    if (-not $branch) {
        throw "Worktree at '$Path' is in a detached HEAD state — cannot push."
    }

    if ($PSCmdlet.ShouldProcess($Path, "Stage, commit '$Message', push '$branch', and prune worktree")) {
        Write-Verbose "Staging all changes in $Path"
        git -C $Path add -A
        if ($LASTEXITCODE -ne 0) { throw "git add failed in '$Path'" }

        # Check if there's anything to commit
        $staged = git -C $Path diff --cached --name-only 2>$null
        if (-not $staged) {
            Write-Warning "Nothing staged to commit in '$Path'"
        }
        else {
            Write-Verbose "Committing: $Message"
            git -C $Path commit -m $Message
            if ($LASTEXITCODE -ne 0) { throw "git commit failed in '$Path'" }
        }

        if (-not $NoPush) {
            Write-Verbose "Pushing branch '$branch' to origin"
            git -C $Path push
            if ($LASTEXITCODE -ne 0) { throw "git push failed for branch '$branch'" }
        }

        if (-not $NoPrune) {
            Write-Verbose "Pruning worktree '$Path'"
            # cd to bare root before removing the worktree beneath us
            Set-Location $root
            git -C $root worktree remove $Path
            if ($LASTEXITCODE -ne 0) {
                Write-Warning "Push succeeded but worktree remove failed. Run: git worktree prune"
            }
            else {
                git -C $root worktree prune
                Write-Host "Worktree saved and removed: $Path" -ForegroundColor Green
            }
        }
        else {
            Write-Host "Committed and pushed from: $Path" -ForegroundColor Green
        }
    }
}