Set-Branch.ps1
|
function Set-Branch { <# .SYNOPSIS Switch the current working tree to a git branch. .DESCRIPTION Uses git switch in the current or specified repository without changing the caller's location. By default the branch must already exist locally; remote branch guessing is disabled. Does not fetch, synchronize branches, create worktrees, or bypass Git's protection for branches checked out in another worktree. Successful operations produce no pipeline output. .PARAMETER Branch Literal branch name. With Track, use an existing remote-tracking branch such as origin/feature/topic; Git derives the new local name feature/topic. Options, full refs, revision expressions and previous-branch shortcuts are not supported. .PARAMETER Path Literal directory inside the working tree. Defaults to the current location. Accepts pipeline paths and objects with Path, RepositoryPath or RepoPath. .PARAMETER CreateNew Create a new local branch at HEAD and switch to it, without an upstream. Fails if the branch already exists, even with Force. Cannot combine with Track. .PARAMETER Force Discard local index and working-tree changes when switching. Git may also overwrite or remove untracked files that obstruct the target checkout. Does not reset an existing branch, bypass worktree protection, or suppress WhatIf/Confirm. .PARAMETER Track Create and switch to a local branch from the supplied remote-tracking branch, setting that remote branch as its upstream. Fails if the inferred local branch already exists. Cannot combine with CreateNew. .OUTPUTS None. .EXAMPLE Set-Branch -Branch feature/topic Switches to an existing local branch, preserving non-conflicting changes. .EXAMPLE Set-Branch -Branch feature/new -CreateNew -Path ../project Creates a branch at that repository's HEAD without changing location. .EXAMPLE Set-Branch -Branch origin/feature/topic -Track Creates feature/topic from origin/feature/topic and sets its upstream. .EXAMPLE Set-Branch -Branch main -Force -WhatIf Previews discarding local changes and switching to main without mutation. .LINK https://git-scm.com/docs/git-switch #> [CmdletBinding(SupportsShouldProcess, DefaultParameterSetName = 'Switch')] param( [Parameter(Mandatory, Position = 0)] [Alias('BranchName')] [ValidateNotNullOrEmpty()] [ValidateScript({ $_ -notmatch '^-|^refs/|[\x00-\x20\x7f]|@\{' -and $_ -ne '@' }, ErrorMessage = 'Branch must be a literal branch name, not an option, full ref, revision expression or checkout shortcut.')] [string]$Branch, [Parameter(Position = 1, ValueFromPipeline, ValueFromPipelineByPropertyName)] [Alias('RepositoryPath', 'RepoPath')] [string]$Path, [Parameter(Mandatory, ParameterSetName = 'Create')] [switch]$CreateNew, [switch]$Force, [Parameter(Mandatory, ParameterSetName = 'Track')] [switch]$Track ) process { $validation = Invoke-Git -Path $Path -Arguments @('check-ref-format', '--branch', $Branch) if ($null -eq $validation) { return } $repositoryPath = $validation.RepositoryPath $arguments = @('switch', '--no-guess') $action = "Switch to branch '$Branch'" if ($Track) { $remote = Invoke-Git -Path $repositoryPath -Arguments @( 'show-ref', '--verify', '--quiet', '--', "refs/remotes/$Branch" ) if ($null -eq $remote) { return } $arguments += '--track=direct' $action = "Create and switch to a local branch tracking '$Branch'" } elseif ($CreateNew) { $arguments += @('--no-track', '--create', $Branch) $action = "Create and switch to branch '$Branch' at HEAD" } if ($Force) { $arguments += '--discard-changes' $action += ', discarding local changes' } $arguments += '--' if (-not $CreateNew) { $arguments += $Branch } if ($PSCmdlet.ShouldProcess($repositoryPath, $action)) { $result = Invoke-Git -Path $repositoryPath -Arguments $arguments if ($null -ne $result) { Write-Verbose "Switched branch in '$repositoryPath'." } } } } |