Files
holocron/plugins/git/skills/git-commits/references/rewrite-history.md
Defame1297 edcc57c0d6 docs: trim skill READMEs and ADR/changelog narration
Two related simplification-audit findings, bundled because they edit
some of the same skill-audit files and splitting would fragment
single-file diffs.

Finding 10: delete 48 per-skill/reference README.md files (they
restated SKILL.md in narrative form and no agent ever loads them) plus
2 scaffold templates. Drop the README criterion from skill-audit's
file-structure.md and finding-criteria.md, and the README-generation
step from skill-author's new-skill.sh; update new-skill.bats to match.
Plugin-root READMEs are kept intentionally, out of scope.

Finding 12: strip historical ADR-0020/ADR-0023 citations and
changelog-style narration from model-facing skill content across
kyberforge and git plugin skills. Delete skill-author's one-time
retrofit.md migration guide and its references. Some ADR-0023 tags
were not narration but check-rtk-prefix's required opt-out marker for
intentionally-bare git commands -- those were restored, not stripped.

Mirror re-synced and full pre-commit/pre-push suite verified green.

Refs: SIMPLIFICATION-AUDIT.md findings 10, 12

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YR2CjVumUbEGWcMikcoXBD
2026-09-12 18:38:09 +00:00

4.9 KiB

source_keys
source_keys
org-commit-conventions
context7-git-htmldocs

Rewriting existing commits

Every flow on this page rewrites history. None of them runs before the caller has explicitly approved it, and none is followed by a force-push to main/master — refuse that and explain why instead.

Amend the last commit

  1. Stage the new changes, or the changes that undo something.
  2. Run rtk git commit --amend, adding --no-edit when the message stays as it is.
  3. If the message should change, show the current one and prompt for the replacement.
  4. The branch has now diverged from its remote. Amending is safe only on a branch nobody else has based work on; on main/master, refuse the force-push and explain, rather than warning and proceeding.

Fold a commit into an earlier one (autosquash — preferred)

Prefer this whenever a commit is written to be folded, because git does the marking:

  1. rtk git commit --fixup=<commit> keeps the target's message; rtk git commit --squash=<commit> lets you edit the combined message later. Both prefix the message with fixup!/squash! and name the target commit.
  2. Get explicit approval — the rebase still rewrites history.
  3. Run git rebase -i --autosquash HEAD~N — bare, not rtk: -i opens an interactive sequence editor. Git pre-fills the todo list with the tagged commits already reordered against their targets; save it unchanged to apply.

-i is not optional here. On Git 2.39.5, git rebase --autosquash HEAD~N without -i prints Successfully rebased and updated refs/heads/<branch>. and exits 0 while leaving the fixup! commit in place at its original SHA — --autosquash is honoured only by the interactive machinery, and the false success is the trap: the fold is reported as done, and the surviving fixup! subject then fails the Conventional Commits commit-msg hook. Later Git versions taught the non-interactive rebase to honour the flag, but -i --autosquash is correct on every version, so always write that.

Squash by hand (interactive rebase)

Use this when the commits were not tagged at commit time. Interactive rebase has no undo once rebase -i starts — git reflog is the recovery path.

  1. Identify the commits to squash — typically the last N on the current branch.
  2. Get explicit approval.
  3. Run git rebase -i HEAD~N — bare, not rtk, for the same interactive-editor reason — marking the older commits squash to keep their messages for editing, or fixup to discard them.
  4. Compose the combined message when the rebase stops to ask. For a non-trivial combined message, follow the structure in references/commit-template.md.

When a rebase halts on a conflict

Offer conflict resolution or rtk git rebase --abort. Do not resolve conflicts automatically without confirmation.

Rebase the branch onto a new base

Replays this branch's commits on top of another branch's tip — bringing a feature branch up to date without a merge commit.

  1. Confirm nothing being replayed has been pushed anywhere someone else has based work on. A rebase gives every replayed commit a new SHA, which breaks any clone that already has the old ones.
  2. Get explicit approval — this rewrites history like every other flow on this page.
  3. rtk git fetch origin first, so <newbase> is the real tip rather than a stale local copy.
  4. rtk git rebase <newbase> — for example rtk git rebase main. Use rtk git rebase --onto <newbase> <upstream> <branch> to replay only the commits after <upstream>, which is how a branch started from the wrong base gets moved.
  5. The branch has now diverged from its remote. It needs --force-with-lease --force-if-includes to push, never a bare --force, and never on main/master — refuse that and explain.

Move the branch pointer back (git reset)

reset moves the current branch to another commit. The mode decides what survives:

Mode Branch pointer Index Working tree
--soft moves untouched — the changes stay staged untouched
--mixed (default) moves reset — the changes become unstaged untouched
--hard moves reset overwritten; uncommitted work is destroyed
  • "Undo my last commit but keep the changes" is rtk git reset --soft HEAD~1. That is the default answer to the request; reach for anything else only when the caller asked for it.
  • rtk git reset --mixed HEAD~1 when the staging should be redone from scratch too.
  • rtk git reset --hard <ref> is gated like a force-push: state exactly which uncommitted changes will be discarded, get approval for that specific reset, and offer rtk git stash push -u first. The commits it drops stay reachable through git reflog; the uncommitted edits never entered git at all and nothing recovers them.

Reset does not rewrite the commits it leaves behind, so no force-push is needed unless the branch was already pushed at the newer commit.