Last active
April 7, 2024 19:00
-
-
Save kkoziarski/51ecacc66dcbe8018e441a530a75d85a to your computer and use it in GitHub Desktop.
Create git worktree from powershell
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Git-Worktree { | |
[CmdletBinding()] | |
Param( | |
[Parameter(Mandatory=$true)] | |
[string]$BranchName, | |
[Parameter(Mandatory=$false)] | |
[switch]$Delete, | |
[Parameter(Mandatory=$false)] | |
[switch]$Current | |
) | |
function Resolve-GitRoot { | |
$dotGitpath = git rev-parse --path-format=absolute --git-common-dir #includes '.git' at the end | |
$gitTopLevel = Split-Path -Path $dotGitpath -Parent | |
if ($LASTEXITCODE -eq 0 -and $gitTopLevel) { | |
return $gitTopLevel | |
} else { | |
Write-Error "Not inside a git repository or unable to find the git repository root." | |
throw "Not a git repository (or any of the parent directories)" | |
} | |
} | |
try { | |
$gitRoot = Resolve-GitRoot | |
} | |
catch { | |
Write-Error "Error: $($_.Exception.Message)" | |
} | |
if ($BranchName -eq 'list') { | |
git worktree list | |
return; | |
} | |
if($BranchName -eq 'master') { | |
Write-Output "Switching to the root of the repository for main branch 'master' at '$gitRoot'" | |
Set-Location -Path $gitRoot | |
return | |
} | |
function Get-GitWorktrees { | |
$worktrees = git worktree list --porcelain | Where-Object { $_ -match '^worktree (.+)' } | ForEach-Object { | |
$Matches[1].Replace('\', '/') | |
} | |
return $worktrees | |
} | |
$existingWorktreePaths = Get-GitWorktrees | |
$worktreePath = Join-Path $gitRoot '.worktrees' $BranchName | |
if ($Delete) { | |
if (Test-Path -Path $worktreePath) { | |
try { | |
Write-Output "Switching to root" | |
Set-Location -Path $gitRoot | |
git worktree remove $worktreePath | |
if ($LASTEXITCODE -ne 0) { | |
throw "Could not remove worktree" | |
} | |
if (Test-Path -Path $worktreePath){ | |
Remove-Item $worktreePath -Recurse | |
Write-Host "'$worktreePath' folder removed successfully." | |
} | |
Write-Output "Worktree for branch '$BranchName' has been removed." | |
} catch { | |
Write-Error "Error: Failed to remove worktree for branch '$BranchName' at '$worktreePath'." | |
} | |
} else { | |
Write-Output "No worktree for branch '$BranchName' at '$worktreePath' exists to remove." | |
} | |
return | |
} | |
$normalizedWorktreePath = $worktreePath.Replace('\', '/') | |
if ($existingWorktreePaths -like "*$normalizedWorktreePath*") { | |
Write-Output "Worktree for branch '$BranchName' already exists at '$worktreePath'. Switching to that directory." | |
Set-Location -Path $worktreePath | |
return | |
} | |
function Create-GitWorktree { | |
param ( | |
[string]$BranchName, | |
[string]$WorktreePath, | |
[switch]$Current | |
) | |
git show-ref --quiet -- "refs/heads/$BranchName" | |
$branchExists = $LASTEXITCODE -eq 0 | |
if (-not $branchExists) { | |
git ls-remote --quiet --exit-code origin "refs/heads/$BranchName" > $null | |
$branchExists = $LASTEXITCODE -eq 0 | |
} | |
if ($branchExists) { | |
git worktree add $worktreePath $branchName | |
} else { | |
$checkoutBranch = $Current ? $null : ($branchExists ? $BranchName : 'master') | |
git worktree add -b $branchName $worktreePath $checkoutBranch | |
} | |
if ($LASTEXITCODE -ne 0) { | |
throw "Could not add new worktree for branch '$BranchName' at '$worktreePath'." | |
} | |
} | |
try { | |
Create-GitWorktree -BranchName $BranchName -WorktreePath $worktreePath -Current $Current | |
Write-Output "Worktree for branch '$BranchName' successfully created at '$worktreePath'." | |
Set-Location -Path $worktreePath | |
} | |
catch { | |
Write-Error "Error: Failed to create worktree for branch '$BranchName' and path '$worktreePath'." | |
} | |
} | |
Set-Alias worktree Git-Worktree | |
Set-Alias gw Git-Worktree |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment