inherit
inherit
Mental model: "I am the child. I want what my parent has."
Brings the current branch (and optionally its descendants) up to date with its parent. Inbound counterpart to /ship (outbound to a target) and /isolate (forks a new child from a parent).
When to use
- Current branch is stale relative to its base.
- A stack of dependent branches needs the parent's latest commits cascaded down.
- Web sessions or minimal environments where
wt,git-trim,gharen't available.
Do NOT use to send changes upward — that's /ship. Do NOT use to create a new branch — that's /isolate.
Why merge, not rebase
Autonomous mode's git-rewrite-guard.sh blocks git rebase, --amend, reset --hard, and push --force*. Merge is also the parallel-worktree community standard for syncing from base — non-destructive, composes with stacks, never requires a force-push, safe under shared checkouts. Always git merge, never git rebase in this skill.
Constraints
- Pure git only. No
wt,git-trim, orghfor the merge step. Works in web sandboxes. - Always
git -C <abs-path>for state-mutating ops.cddoes not persist between Claude Code Bash calls; baregitfrom session CWD hits the primary worktree. - Never auto-resolve conflicts. The user owns conflict resolution.
Inputs
| Flag | Purpose |
|---|---|
--stack |
Cascade the merge bottom-up through dependent branches |
--parent <name> |
Override auto-detected parent |
--no-push |
Skip the push step (commits stay local) |
CI-down signal: same convention as /ship — if user has signaled CI is down, substitute /local-merge for each git push.
Procedure
1. Resolve current branch + repo root
REPO="$(git rev-parse --show-toplevel)"
CURRENT="$(git -C "$REPO" rev-parse --abbrev-ref HEAD)"
Pre-flight aborts:
CURRENTisHEAD(detached) → "No current branch — checkout a branch first."- Working tree dirty (
git -C "$REPO" status --porcelainnon-empty) → "Commit or stash local changes before inheriting."
2. Detect parent (unless --parent was passed)
PARENT=$(git -C "$REPO" reflog show HEAD --pretty=format:'%gs' \
| grep -m1 '^branch: Created from ' \
| sed -E 's/^branch: Created from //; s|^origin/||')
PARENT="${PARENT:-main}"
grep -m1picks the most recent "Created from" — that's the actual fork point.- Strip leading
origin/so we work in branch-name space. - Fall back to
mainwhen reflog is empty (web sessions, fresh clones, branches created via fetch). Tell the user it was a fallback so they can correct via--parent. - If
PARENT == CURRENTafter resolution → "Already on parent branch; nothing to inherit."
Echo before mutating: Detected parent: <PARENT> (current: <CURRENT>). Inheriting from origin/<PARENT>.
3. Fetch the parent
git -C "$REPO" fetch origin "$PARENT"
If fetch fails (offline, ref missing, parent deleted on origin): surface the error verbatim. Do NOT silently substitute another branch.
4. Merge parent into current
git -C "$REPO" merge --no-edit "origin/$PARENT"
Outcomes:
- Clean (real merge or fast-forward) → proceed.
- No-op (already up to date) → say so plainly and skip the push.
- Conflict → stop, show
git status, list conflicted paths, hand control back. Do NOT attempt automatic resolution.
5. Cascade through stack (only if --stack)
A "dependent" is a local branch with CURRENT as an ancestor. The user supplies the candidate set after --stack (or names them inline); don't guess silently — if the user didn't name them, ask once.
Order: bottom-up, parent-first. Use pairwise git merge-base --is-ancestor to find topological order — at each step, pick a branch in the remaining set that no other remaining branch is an ancestor of. That branch goes next:
# B is downstream of A iff A is an ancestor of B
git -C "$REPO" merge-base --is-ancestor "$A" "$B" # exit 0 = yes
For each branch in that order, merge its direct parent in the chain (the previous branch processed) — NOT origin/main again. The whole point of cascading is that the parent already absorbed main, and now the child absorbs the updated parent:
PREV="$CURRENT"
for child in "${ordered[@]}"; do
git -C "$REPO" checkout "$child"
git -C "$REPO" merge --no-edit "$PREV" # stop on conflict
PREV="$child"
done
git -C "$REPO" checkout "$CURRENT"
On conflict: stop the cascade. Report which branch wedged and which paths conflict. Do NOT skip forward.
6. Push (or /local-merge if CI is down)
For each branch that received commits (CURRENT plus any cascaded children):
git -C "$REPO" push origin "$BRANCH"
If user has signaled CI is down: invoke /local-merge per branch instead.
If --no-push was passed: skip entirely; tell the user the branch(es) have local merge commits awaiting publish.
If push is rejected (remote moved): do NOT force. Report the rejection; the user decides whether to re-run /inherit.
7. Report
Concise summary, not paragraphs:
Inherited from <PARENT> into:
- <CURRENT> (merge <sha>, pushed)
- <child-1> (merge <sha>, pushed)
On conflict:
Inherit halted on <branch>: conflicts in <files>. Resolve, commit, then re-run /inherit.
Quick reference
| Step | Command |
|---|---|
| Detect parent | git reflog show HEAD --pretty=format:'%gs' | grep -m1 '^branch: Created from' |
| Fetch | git -C "$REPO" fetch origin "$PARENT" |
| Merge in | git -C "$REPO" merge --no-edit "origin/$PARENT" |
| Stack order | git merge-base --is-ancestor <a> <b> pairwise, root-first |
| Push | git -C "$REPO" push origin <branch> |
| CI down | /local-merge per branch |
Failure modes — explicit counters
| Rationalization | Counter |
|---|---|
| "Rebase is cleaner — I'll just rebase onto main" | Forbidden. Rewrite-guard blocks it in autonomous mode. Use merge. |
| "Reflog is empty, I'll guess from branch-name patterns" | Fall back to main. Tell the user. Do not infer from naming. |
| "I'll force-push after a tidy rebase" | Forbidden. No --force, --force-with-lease, or --amend in this skill. |
"I'll use git pull --rebase" |
Same prohibition as git rebase. Use plain git merge. |
"I'll use wt sync / git-trim" |
Pure git only — those binaries aren't in web sessions. |
| "Stack order doesn't matter, I'll merge in any order" | Merge bottom-up (root-adjacent first) so each child sees its updated parent. |
| "I'll skip the push" | Push each updated branch unless CI-down or --no-push applies. |
"Conflict? I'll auto-resolve with -X theirs" |
Never. The user owns conflict resolution. Stop and report. |
Red flags — STOP
- About to type
git rebase,--amend,reset --hard, or--force→ wrong skill. - Parent detection silently returned empty and you didn't fall back to
main. - Merging top-down through a stack (parent-most last) → reverse the order.
- Bare
gitwithout-Cfrom session CWD on a non-primary worktree. - Modifying files outside git operations — this skill is pure git.
Companion skills
/isolate— forks a new child off a parent./inherit(this skill) — pulls parent → child. Inbound./ship— pushes child → target. Outbound.
Three directions a branch moves: fork off, sync down, ship up.
Example invocations
- "pull main into this branch" →
/inherit - "update my stack from main" →
/inherit --stack - "sync from base but don't push yet" →
/inherit --no-push - "catch up to develop instead of main" →
/inherit --parent develop
More from camacho/ai-skills
bail
Reflects, updates GitHub Issue, closes PR if open, cleans up worktree/branch.
413plan-review
Auto-assembles review panel using deterministic rules, dispatches agents against plan file, collects verdicts.
396archive
Fills Outcomes & Learnings in a plan file and renames it to .done.md.
388orient
Fetches issue context, auto-detects task type, maps to branch prefix, presents brief.
386capture
Creates a draft GitHub Issue with triage label from natural language description.
384reflect
Use after merging a branch or completing a task to consolidate learnings into memory layers, close out issues, and verify the phase gate.
346