local-merge
Original:🇺🇸 English
Translated
Use when merging a branch to main without touching the primary worktree directly, when /ship or /reflect needs to integrate work, or when autonomous mode blocks direct main commits
40installs
Sourcecamacho/ai-skills
Added on
NPX Install
npx skill4agent add camacho/ai-skills local-mergeTags
Translated version includes tags in frontmatterSKILL.md Content
View Translation Comparison →/local-merge
Merge a branch into a target branch via a disposable shallow clone, then propagate to the primary worktree non-destructively. Defaults to main if no target specified.
Inputs
| Input | Required | Default | Example |
|---|---|---|---|
| yes | — | |
| no | | |
| no | First line of | |
| no | | |
Phase 1 — Remote Merge (mechanical)
All commands are explicit. No reasoning required.
1a. Calculate clone depth
bash
git fetch origin "$TARGET" "$BRANCH"
DEPTH=$(( $(git rev-list --count origin/"$TARGET"..origin/"$BRANCH") + 10 ))1b. Clone, merge, push
bash
MERGE_DIR="${CLAUDE_SESSION_DIR:-/tmp}/local-merge-$$"
[ -d "$MERGE_DIR" ] && rm -rf "$MERGE_DIR"
git clone --depth "$DEPTH" --branch "$TARGET" "$(git remote get-url origin)" "$MERGE_DIR"
git -C "$MERGE_DIR" fetch origin "$BRANCH"
git -C "$MERGE_DIR" merge FETCH_HEAD -m "$MESSAGE"
git -C "$MERGE_DIR" push1c. Non-fast-forward recovery
bash
git -C "$MERGE_DIR" pull --rebase
git -C "$MERGE_DIR" pushMax 3 retries. After 3 failures, stop and report. Do not force-push.
1d. Cleanup
Always runs after Phase 1, success or failure:
bash
rm -rf "$MERGE_DIR"Phase 2 — Propagate to Primary (reasoning required)
Bring the primary worktree's up to date with the newly-pushed remote. Steps 2a-2c are mechanical. Step 2d requires agent judgment. Steps 2e-2g depend on that judgment.
$TARGET2a. Guard: is primary on TARGET?
bash
git -C "$PRIMARY" branch --show-currentNot on ? Stop. Report: "Primary is on , not . Remote updated; local not forwarded." Done.
$TARGET<branch>$TARGET2b. Protect dirty state
bash
git -C "$PRIMARY" status --porcelainIf output is non-empty, shelter uncommitted work:
bash
git -C "$PRIMARY" add -A
git -C "$PRIMARY" commit -m "wip: preserve local state before remote sync"Record for step 2g. If clean, skip.
WIP_CREATED=true2c. Fetch updated TARGET
bash
git -C "$PRIMARY" fetch origin "$TARGET"2d. Analyze divergence (agent reasoning)
Run all five commands, then assess using the decision matrix:
bash
git -C "$PRIMARY" rev-list --count HEAD..origin/"$TARGET" # commits behind
git -C "$PRIMARY" rev-list --count origin/"$TARGET"..HEAD # commits ahead
git -C "$PRIMARY" diff HEAD..origin/"$TARGET" --stat # changed files
git -C "$PRIMARY" log HEAD..origin/"$TARGET" --oneline # incoming commits
git -C "$PRIMARY" log origin/"$TARGET"..HEAD --oneline # local-only commits| Behind | Ahead | Assessment | Action |
|---|---|---|---|
| N > 0 | 0 | Fast-forward | |
| N > 0 | M > 0 | Diverged | Inspect diff for file overlap + semantic risk (2e) |
| 0 | 0 | Already current | Skip, report, done |
| 0 | M > 0 | Local-only commits | Unexpected — escalate to copilot (2f) |
Beyond textual conflicts, assess semantic risk: two agents editing related config in different files can silently break things even when git sees no conflict.
2e. Execute merge
Fast-forward (behind > 0, ahead = 0):
bash
git -C "$PRIMARY" merge --ff-only origin/"$TARGET"Non-conflicting divergence (different files, low semantic risk):
bash
git -C "$PRIMARY" merge origin/"$TARGET" --no-editIf merge produces conflicts, abort immediately:
bash
git -C "$PRIMARY" merge --abortThen escalate to copilot (2f).
Uncertain or risky: do not attempt merge. Go to 2f.
2f. Copilot escalation
- Invoke to enter copilot mode
/copilot - Present the analysis from 2d: behind/ahead counts, diff stat, commit logs
- State what blocked automatic resolution
- Let the user drive the merge
- When resolved, invoke to restore previous mode
/autonomous
2g. Restore WIP state
Only if :
WIP_CREATED=truebash
git -C "$PRIMARY" reset --soft HEAD~1Preserves all changes in the index and working tree exactly as they were before the skill ran.
Safety Invariants
- No force-push. Non-fast-forward retries use , never
pull --rebase.--force - No work lost. Dirty state is WIP-committed before any merge, restored after.
- No direct commits to main. Phase 1 uses a disposable clone for multi-agent isolation regardless of target. Phase 2 only fast-forwards or merges from origin.
- Conflict = stop. Conflicts trigger and copilot escalation, never auto-resolution.
merge --abort - Cleanup always runs. The shallow clone is removed regardless of outcome.
Integration
| Caller | Context |
|---|---|
| CI-down path after review approval |
| Post-task consolidation to main |
| Receives escalation from Phase 2f |
| Restored after copilot resolves conflict |