sync
Wraps bin/sync.sh. Rebases (or merges) the current feature branch
onto its base, after a clean-tree + branch-safety check.
1. Pre-flight (the script does these; your job is to interpret them)
- Not a git repo (exit 2) → tell the user; stop.
- Detached HEAD / main / master / develop (exit 2) → refuse with
a clear message; suggest switching to a feature branch first
(
/nyann:branchcreates one). - Dirty working tree (status=
dirtyin JSON) → stop and tell the user to commit or stash first. Don't silently stash on their behalf —git stashis a footgun when the rebase also conflicts.
2. Choose strategy
Default to rebase. Use merge when:
- The user explicitly says "merge" (not "rebase").
- The profile's branching strategy is
gitflowand the target base isdevelop/main(shared long-lived branches — some teams ban rebase on these). - The branch has already been pushed to a shared remote and has open PRs (rebasing rewrites history; merges don't).
If unclear, you MUST call the AskUserQuestion tool (not plain text):
{
"questions": [
{
"question": "How should upstream changes be integrated?",
"header": "Strategy",
"multiSelect": false,
"options": [
{ "label": "Rebase (Recommended)", "description": "Keeps history linear; replays your commits on top of base" },
{ "label": "Merge", "description": "Preserves original commits; adds a merge commit" }
]
}
]
}
3. Resolve base
bin/sync.sh picks base via: --base > @{upstream} > origin/HEAD
main. Override only when the user explicitly names a different target ("sync against develop"). Normally trust the resolution.
4. Invoke
bin/sync.sh --target <cwd> [--strategy rebase|merge] [--base <branch>] [--dry-run]
--dry-run reports what would happen without mutating. Use it when
the user is cautious or you want to show them the ahead/behind count
first.
5. Interpret the output JSON
| status | meaning | what to tell the user |
|---|---|---|
up-to-date |
behind == 0 | "Already up to date with <base>." No action needed. |
synced |
operation completed | "Synced via <strategy>. Now <ahead> ahead, 0 behind." |
dirty |
working tree had uncommitted changes | "Working tree has uncommitted changes. Commit or stash first." |
skipped |
base not found locally or on origin | "Couldn't find <base> locally or on origin. Check the branch name." |
conflicts |
rebase/merge halted mid-operation | See §6 — this is the tricky case. |
6. When conflicts happen
The script stops and leaves the working tree in a rebase-in-progress or merge-in-progress state. Do NOT call sync again — the script doesn't know how to resume.
Read the conflicts[] array from the JSON. For each file, offer to
help resolve it (read the file, show conflict markers, ask the user
which side to keep). When the user is done:
- For rebase:
git add <resolved-files>thengit rebase --continue. - For merge:
git add <resolved-files>thengit -c user.email=... -c user.name=... commit --no-editto finalize.
If the user wants to bail: git rebase --abort or git merge --abort.
Either returns the working tree to its pre-sync state.
When to hand off
- "Now push and PR" →
prskill. - "The conflicts are too messy, just abort" → run
git rebase --abort/git merge --abortyourself and confirm. - "Update main itself" → out of scope; tell the user
git checkout main && git pullhandles that.