LyAhn a980153b3e feat: own the branch synchronization engine
Replace the external hub sync dependency with an attributed internal implementation that fetches and updates branches independently. Allow dirty repositories while protecting affected checked-out branches, retain all-clean strict mode, add real-remote safety tests, and update the CLI, TUI, JSON output, version, and documentation.
2026-09-06 19:41:53 +01:00

Stack Sync

stack-sync safely fetches and synchronizes local branches across every Git repository in a workspace. It is designed for directory trees such as JezzWTF where the root may not be a repository and a parent repository may contain deliberately untracked, nested repositories.

It provides both a full-screen Bubble Tea control deck for interactive work and a conventional CLI/JSON interface for SSH sessions and automation. Both interfaces use the same discovery and safety engine.

Safety model

Before a repository is eligible, Stack Sync verifies that it:

  • is on a branch (not a detached HEAD);
  • has at least one remote;
  • has no merge, rebase, cherry-pick, revert, or bisect in progress.

Modified, staged, deleted, conflicted, and untracked files are reported but do not block the repository by default. If the checked-out branch would otherwise be fast-forwarded or deleted, Stack Sync protects that branch and continues synchronizing safe inactive branches. Branches checked out in another linked worktree are protected too. Use --strict when every repository must be completely clean before anything is synchronized.

Untracked paths that are themselves discovered nested Git repositories are excluded from the parent repository's dirty report. All other worktree changes remain visible in the CLI, JSON, and TUI.

Stack Sync never runs git stash, git reset, git clean, git commit, or any other command that saves or discards work. A repository is checked again immediately before synchronization, and the worktree is checked again before changing its checked-out branch.

The branch behavior is derived from the MIT-licensed hub sync implementation and is now built directly into Stack Sync. It fetches and prunes the main remote, fast-forwards outdated branches, warns about divergent/unpushed branches, and removes a branch only when its configured upstream was deleted and the branch is already merged into the remote default branch. It prefers a remote named upstream, github, or origin; a sole differently named remote is also accepted. See third-party notices for attribution.

Requirements

Stack Sync supports Linux and Windows. It requires:

  • Go 1.24 or newer to build;
  • Git on PATH.

There is no separate hub dependency.

Build and install

go install is the simplest cross-platform installation method. From the repository root, run:

go install .

Go automatically installs stack-sync on Linux and stack-sync.exe on Windows into your Go binary directory. Make sure that directory is on PATH (normally $HOME/go/bin on Linux and %USERPROFILE%\go\bin on Windows).

To build a binary in the repository instead, use the command for your platform.

Linux

cd stack-sync
go test ./...
go build -o stack-sync .
install -Dm755 stack-sync ~/.local/bin/stack-sync

Windows (PowerShell)

Set-Location stack-sync
go test ./...
go build -o stack-sync.exe .
New-Item -ItemType Directory -Force "$env:LOCALAPPDATA\Programs\stack-sync" | Out-Null
Copy-Item .\stack-sync.exe "$env:LOCALAPPDATA\Programs\stack-sync\stack-sync.exe"

Add %LOCALAPPDATA%\Programs\stack-sync to your user PATH if it is not already present. The .exe suffix is important when choosing an explicit output name on Windows; go build -o stack-sync . creates an extensionless binary there.

Usage

Interactive TUI

Launch the control deck for the workspace:

stack-sync tui --root ~/Coding/jwtf

PowerShell accepts the same options with a Windows path:

stack-sync tui --root C:\Users\you\Coding\jwtf

Every eligible repository starts selected. Dirty repositories remain selectable and are labelled ready (dirty); their checked-out branches are protected if an update would affect them. Move with the arrow keys or j/k, toggle the focused repository with Space, select all with a, clear the selection with n, and refresh with r. Press s or Enter to review the branch-deletion warning, then y to begin. Blocked repositories cannot be selected. After a run, focusing a repository shows its latest per-branch results.

CLI and automation

Scan the current workspace. This is read-only and is the default command:

stack-sync scan --root ~/Coding/jwtf
# equivalent:
stack-sync --root ~/Coding/jwtf
stack-sync scan --root C:\Users\you\Coding\jwtf

Review the same plan, confirm it, and sync every eligible repository:

stack-sync sync --root ~/Coding/jwtf

For automation, suppress the prompt and optionally require the entire workspace to be clean. In strict mode, either a blocked repository or any worktree change aborts the whole run:

stack-sync sync --root ~/Coding/jwtf --yes --strict

Useful options:

--jobs 4             maximum concurrent inspections or syncs
--timeout 5m         per-repository fetch and sync timeout
--exclude temp       skip a directory name anywhere in the tree
--exclude Org/old    skip a root-relative path
--json               emit structured output

Both / and \ are accepted in Windows paths. Quote a root or exclusion containing spaces, for example --root "C:\Users\you\Source Repositories".

Dependency caches, build outputs, and tool-managed directories such as node_modules, target, .claude, and .codex are skipped during discovery by default. These exclusions only affect repository discovery; they never make real changes inside a discovered repository disappear from its dirty-worktree check.

Exit codes are 0 for a successful scan or sync (including protected branches and divergence warnings), 1 for an operational/sync failure, 2 for invalid or unconfirmed non-interactive use, and 3 when strict mode refuses the plan or a previously eligible repository fails its immediate pre-sync safety check.

S
Description
Safely discover and synchronize every Git repository in a nested workspace
Readme 151 KiB
Languages
Go 100%