Files
holocron/plugins/git/skills/git-branches/references/branch-operations.md
Defame1297 20e5627fd7 fix(git): correct three command claims the plugin got wrong, and give rebase an owner
Three statements were false against the git in use (2.39.5), each verified by
running it.

`git rebase --autosquash HEAD~N` without `-i` is a silent no-op: git prints
"Successfully rebased", the `fixup!` commit survives with the same SHA, and
rewrite-history.md presented that as the preferred flow with `-i` as an optional
review step. The agent reports the squash as done and the `fixup!` subject then
trips this repo's own commit-msg gate. `-i` is now the command, not the alternative.

"Fetch never modifies a local branch, so it is always safe to run" — new text on
this branch — is false: `git fetch origin main:probe` fast-forwarded the local
branch, and a `+` prefix force-updates it, losing commits. The claim is scoped to
the no-refspec form.

`git worktree add --orphan` does not exist before Git 2.42; on 2.39.5 it is
`error: unknown option 'orphan'`, exit 129. The same file gives a version floor for
`--recurse-submodules` three sections earlier. Floor added, with a fallback that
was tested before being documented.

git-workflow claimed "every request resolves to exactly one of these six" while
rebase, reset and stash were owned by no skill — `git reset` appeared nowhere in
the plugin, old tree or new — so "undo my last commit" routed nowhere. The claim is
gone, the router gains rows for all three, and the procedures now exist: plain
rebase with `--onto` and conflict handling, a reset mode table gated on `--hard`,
and stash save/pop/list/drop. `--hard` gets an always-loaded Gotcha, matching the
register the force-push refusal already sets.

Cherry-pick had three claimants pointing at git-history while git-commits owned the
flow, and the two copies were not equivalent — git-history's lacked the destination
check, the rtk prefix and `--abort`. Resolved to git-commits per #112; the weaker
duplicate is replaced by a hand-off.

git-commits' metadata.version was deleted rather than bumped in 14af50b, leaving two
house-contract documents citing a worked v0.1.2 to v0.1.3 transition against a file
declaring no version. Restored to 0.1.3.

Also: the divergent-pull explanation stated a `--ff-only` default that does not
exist (it is a hard error); `--remote` "requires" a configured branch where it uses
one; `git push origin --delete` moved to git-remotes, which owns the remote-side
gates; seven retired `git:<name>` source slugs; git-orchestrate quoted a
git-workflow sentence that no longer exists; git-submodules regains the indirect
trigger that made "add a dependency repo" routable; and commit atomicity is a common
gate rather than reachable only from the create flow.

Refs: #112, #113
2026-09-01 12:38:38 +00:00

3.3 KiB

source_keys
source_keys
context7-git-htmldocs

Per-action command mapping

One command per action. Where two forms exist, the first is the default and the second the escape hatch.

  • create — git switch -c <branch> <base>. Base comes from the config's base_branch (main under GitHub Flow, usually develop under Gitflow).
  • switch — git switch <branch> moves to an existing local branch; it aborts rather than clobbering conflicting local changes. git switch - returns to the previous branch.
  • delete (local) — git branch -d <branch> refuses when the branch holds unmerged commits, which is why it is the default. git branch -D <branch> forces the deletion and discards that work — only after the destructive-operation gates pass and confirm: true is set.
  • delete (remote) — not this skill's. Deleting a remote branch is a push, and every remote-side gate lives in git-remotes; hand it there rather than running the push from here. Its references/push.md carries the command and the refspec form.
  • rename — git branch -m <old> <new>.
  • list — git branch (local), -a (local plus remote-tracking), -r (remote-tracking only), --merged / --no-merged (filter by merge status into the current branch).
  • track — git branch --set-upstream-to=origin/<branch> sets an upstream without pushing. git branch -vv shows the tracking state of every local branch.

get-intent

Git has no native field for free-text branch metadata, and this skill does not persist any. On create, the intent value is only returned in the structured result — the caller decides whether to store it.

On get-intent, either parse the intent back out of the branch-name convention (feature/<intent-slug>) or return { "intent": null } when the caller never persisted the create-time value. Never fabricate an intent: a downstream commit message built on a guessed intent is worse than one built on none.

Stashing work in progress

A switch aborts rather than clobbering conflicting local changes (see Gotchas). Stash is the way past it: it shelves the working tree and index so the branch pointer can move.

  • save — git stash push -m "<message>". Add -u to include untracked files; verified on Git 2.39.5, a plain push leaves them in place, and a plain push with only untracked changes reports No local changes to save and stashes nothing. Bare git stash is push with no message.
  • restore — git stash pop applies the newest entry and deletes it. git stash apply stash@{n} applies without deleting, for replaying one shelf onto more than one branch.
  • list — git stash list; git stash show -p stash@{n} prints that entry's diff.
  • drop — git stash drop stash@{n} deletes one entry. git stash clear deletes all of them and nothing recovers them — confirm before running it.
  • branch from a stash — git stash branch <branch> stash@{n} creates a branch at the commit the stash was taken from and pops it there. Use it when the stash no longer applies to the current tip.

A conflicting pop keeps the entry. Verified on 2.39.5: it exits 1, writes conflict markers, prints "The stash entry is kept in case you need it again", and git stash list still shows it. Resolve, git add, then git stash drop the entry by hand — otherwise it silently accumulates.