This file defines the Git commands behind each workbranch Git operation.
workbranch keeps the user-facing model small, but the implementation still uses ordinary Git commands. Use this file as the maintenance contract for Git behavior.
The source-level definitions live in apps/cli/src/workbranch/git-ops.sh.
bin/workbranch is the generated single-file install artifact.
Vertical:
pull remote base -> local base
push local base -> remote base
Horizontal:
update local base -> task
land task -> local base
Composite:
refresh remote base -> local base, then local base -> task
Maintenance:
doctor inspect project health; --fix prunes stale worktree registrations
and prepends a missing task brief H1 when safe
Optional:
push <task> task -> remote task branch
Direction: base/source ref -> task worktree.
Before creating worktrees, workbranch add [<task>] [--from <ref>] resolves the task key, shows each repo's configured base branch, then prompts for that repo's task branch. On main/master-style bases, zero-arg workbranch add asks for task type and detail name and derives the recommended task key type-detail. When every repo shares the same parent feature base, such as feature/cpq, zero-arg workbranch add asks only for the task name and creates the mirrored task folder feature-cpq-<name> for branch feature/cpq-<name>. In an interactive terminal, workbranch add <name> follows that same base-aware prompt flow with <name> prefilled. workbranch add type-detail remains a direct conventional shorthand. Non-interactive task keys without the conventional type- prefix keep legacy defaults for script compatibility. The chosen task branches are saved in <task>/.workbranch.task; the optional --from ref is only the starting source, is not stored as the task branch, and does not become a persistent status comparison baseline.
For each repo:
cd _base/<repo>
git fetch origin
git worktree add <task>/<repo> -b <task-branch> HEADWith --from <ref>, workbranch fetches origin and resolves the source ref per repo. Bare refs such as feat/x prefer origin/feat/x when present; explicit origin/feat/x, refs/..., HEAD, and existing local refs are also accepted.
git fetch origin
git worktree add <task>/<repo> -b <task-branch> <resolved-source-ref>If the task branch already exists locally or remotely, workbranch add [<task>] fails. For local task branches, run workbranch remove <task> to delete the local branch before adding again. For remote-only task branches, delete or rename the remote branch outside workbranch before adding again.
Safety:
- Rolls back worktrees and new branches created by the command if worktree creation fails.
- Keeps created worktrees if a configured setup command fails, prints the failed setup directory and command, and tells the user to fix setup with
workbranch config, then rerun the shown command or remove and add the task again. - Uses the local base worktree HEAD, not
origin/<base-branch>. workbranch remove <task>deletes local task branches, so adding the same task after remove starts from the current local base again.
Direction: remote base -> local base.
For each repo:
cd _base/<repo>
git pull --ff-only origin <base-branch>Safety:
- Fails before running if the local base worktree is dirty.
- Uses
--ff-only; no merge commit is created.
Direction: local base -> every task.
For each task and repo:
cd <task>/<repo>
git rebase <_base/<repo> HEAD>Safety:
- Fails before running if the task worktree is dirty.
- Uses the local base worktree HEAD, not
origin/<base-branch>. - Fails before running if
_base/<repo>is not checked out to the configured base branch. - Fails before running if
_base/<repo>has a rebase in progress. - Conflict resolution is left to Git and the user.
Direction: remote base -> local base, then local base -> task workspace(s).
Without <task>, workbranch refresh targets every task workspace. With <task>, it targets only that task workspace. For each repo, refresh first validates that every target task workspace can be updated. If there are no task workspaces, or any target task worktree is dirty, missing, on the wrong branch, or has a rebase in progress, the command fails before pulling base branches.
After update preflight passes, refresh runs the same base pull behavior as workbranch pull:
cd _base/<repo>
git pull --ff-only origin <base-branch>Then it runs the same task rebase behavior as workbranch update for the task set collected before the pull:
cd <task>/<repo>
git rebase <_base/<repo> HEAD>Safety:
- Fails before pulling if task updates cannot run.
- Pull failures abort before any task update.
- Uses existing pull and update Git operations; refresh does not introduce a separate Git primitive.
Direction: local base -> one task.
For each repo in the task:
cd <task>/<repo>
git rebase <_base/<repo> HEAD>Safety is the same as workbranch update.
Direction: task -> local base.
For each repo in the task:
cd _base/<repo>
git checkout <base-branch>
git pull --ff-only origin <base-branch>
git merge --ff-only <task-branch>Safety:
- Fails before running if the task worktree or local base worktree is dirty.
- Uses
--ff-only; no merge commit is created. - Updates the local base from remote before landing the task.
Direction: inspect local filesystem, Git worktree metadata, and task-root brief format. With --fix, prune stale worktree registrations and apply the safe task brief H1 repair.
workbranch doctor reports base worktree issues, partial task workspaces, stale task directories, prunable worktree registrations, and content-bearing task briefs that parse to zero Plans because they have no # <plan> H1. It is read-only by default and exits 0 only when no issues are found.
With --fix, for each in-scope base repo:
cd _base/<repo>
git worktree pruneFor a content-bearing task brief with no H1, --fix may prepend a single heading:
# <task>It never rewrites, reorders, or promotes existing brief content. It creates no backup; undo is removing the inserted first line. If checklist items remain under ## note sections, doctor --fix reports that manual promotion to # Plan headings is still required and exits non-zero until that manual action is resolved.
Safety:
--fixnever deletes task directories or branches.- Task brief repair only prepends a missing
# <task>H1 and leaves all existing content in place. - Stale task directories are reported with
workbranch remove <task>guidance. - Base branch drift, dirty worktrees, rebases in progress, and partial workspaces are reported only.
--repo <repo>scopes repo/worktree diagnosis and pruning to that repo; task brief format checks remain per-task and are not repo-scoped.
Direction: local base -> remote base.
For each repo:
cd _base/<repo>
git push origin <base-branch>Direction: task -> remote task branch.
For each repo in the task:
cd <task>/<repo>
git push -u origin <task-branch>For each repo, task branch names are explicit values chosen at workbranch add prompts. The recommended task folder depends on the base shape. Interactive add <name> pre-fills that name in the base-aware creation flow; non-interactive task keys without the conventional type- prefix keep the legacy defaults:
base master + interactive name login -> folder feat-login -> branch feat/login
base feature/cpq + interactive name task1 -> folder feature-cpq-task1 -> branch feature/cpq-task1
base feature/cpq + explicit feat-task1 -> folder feat-task1 -> branch feature/cpq-task1
base master + non-interactive login -> folder login -> branch feature/login
base feature/cpq + non-interactive task1 -> folder task1 -> branch feature/cpq-task1
task key feat-login + override tk/login -> tk/login
Chosen branches are persisted in <task>/.workbranch.task. Later commands resolve task branches in this order:
REPO_BRANCH <repo> <branch>in<task>/.workbranch.task- The existing task repo's current branch
- Stale Git worktree registration for manually removed task directories
- The default branch rule above
Remove linked worktrees and local task branches for a task. Remote task branches are not deleted.
If the task worktree directory was removed manually, workbranch remove <task> still deletes the local task branch when workbranch can identify it from metadata, an existing task worktree, stale Git worktree registration, or the default branch rule.
Fails if any task worktree is dirty. Use workbranch remove <task> --force to discard dirty local task worktrees and local task branches.