Keeping local PR worktrees current with master¶
scripts/dev/sync-worktrees-with-master.ps1 keeps every local PR worktree
merged up with origin/master so in-flight branches don't drift and
master/branch conflicts surface early instead of at merge time.
What it does¶
On each run it:
git fetch origin master.- Resolves the set of open-PR head branches via
gh pr list. - Walks
git worktree list; for every worktree whose branch is one of those open-PR branches, mergesorigin/masterin.
Safety rules (a sweep must never damage in-progress work):
| Situation | Behaviour |
|---|---|
| Branch already contains master | skipped as current |
| Worktree has uncommitted changes | skipped as skipped-dirty (untouched) |
| Merge hits conflicts | git merge --abort, reported as conflict — left exactly as found |
| Clean merge | merged (local only) |
| Open PR with no local worktree | ignored (nothing to merge into) |
It is a merge, never a rebase — no history rewrite, no force-push, safe for shared/pushed PR branches.
Usage¶
# preview only
./scripts/dev/sync-worktrees-with-master.ps1 -DryRun
# local sweep (default): merge master into clean PR worktrees
./scripts/dev/sync-worktrees-with-master.ps1
# also push clean merges back to each PR branch (triggers pr-ci per branch)
./scripts/dev/sync-worktrees-with-master.ps1 -Push
-Push is opt-in on purpose: pushing N branches kicks off N pr-ci runs on the
self-hosted runners. The default keeps the work local; push the branches you
care about by hand, or schedule a -Push run at a quiet hour.
Exit code is non-zero when any branch ends in conflict, so a scheduler can
alert.
Automating it (Windows Scheduled Task — polling)¶
There is no local push webhook from GitHub, so we poll: a Scheduled Task runs
the sweep every ~10 min. When origin/master hasn't moved every branch reports
current and nothing is written, so the poll is cheap.
Register it (runs as the logged-on user so it inherits your git + gh creds;
hidden window; logs to %TEMP%\sync-worktrees.log):
$repo = 'C:\repos\rakletv3'
$script = "$repo\scripts\dev\sync-worktrees-with-master.ps1"
$log = "$env:TEMP\sync-worktrees.log"
# Windows PowerShell 5.1 -- always at a fixed path Task Scheduler resolves. The
# store/MSIX pwsh.exe alias does NOT activate under Task Scheduler, so use 5.1
# (the script is 5.1-compatible) and let it pass -LogPath for an inspectable run.
$exe = "$env:SystemRoot\System32\WindowsPowerShell\v1.0\powershell.exe"
$action = New-ScheduledTaskAction -Execute $exe -WorkingDirectory $repo `
-Argument "-NoProfile -NonInteractive -WindowStyle Hidden -ExecutionPolicy Bypass -File `"$script`" -LogPath `"$log`""
$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) `
-RepetitionInterval (New-TimeSpan -Minutes 10)
$settings = New-ScheduledTaskSettingsSet -StartWhenAvailable `
-MultipleInstances IgnoreNew -ExecutionTimeLimit (New-TimeSpan -Minutes 15)
Register-ScheduledTask -TaskName 'RakletSyncWorktreesWithMaster' `
-Action $action -Trigger $trigger -Settings $settings `
-RunLevel Limited -Description 'Merge origin/master into open-PR worktrees every 10 min'
Inspect / remove:
Get-ScheduledTaskInfo RakletSyncWorktreesWithMaster # last/next run + result
Get-Content $env:TEMP\sync-worktrees.log -Tail 40 # what it did
Unregister-ScheduledTask RakletSyncWorktreesWithMaster -Confirm:$false
The task runs only while the user is logged on (it needs your git/gh credentials). On the dev VM the default terminal is pinned to conhost, so
-WindowStyle Hiddensuppresses the window cleanly (unlike Windows Terminal, which ignores it).