re0-git
Rewrite a finished commit's message into a clean, handoff-ready form in your own log style, and place a late commit in time order on a linear history, so `git log` alone tells the story. User-invoked: run it once you've decided to commit.
Try your first task
A source-grounded starter task has not been verified for this skill yet.
SKILL.md
name: re0-gitdisable-model-invocation: truedescription: "Rewrite a finished commit's message into a clean, handoff-ready form in your own log style, and place a late commit in time order on a linear history, so `git log` alone tells the story. User-invoked: run it once you've decided to commit."Rewrite a finished commit message so the log supports handoff in the author's voice, and place a late commit where its time falls.
Goal
Repeated amends and momentum commits leave messages bloated, stale, or padded with trivia, and a change committed late lands out of time order. re0-git refines the author's message so a fresh session can continue from git log alone, without the diff. It changes only messages and where a late commit sits; content and every date already written stay put.
It is user-invoked: run it once you've decided to commit. Giving an agent autonomous access to commit cleanup would bias it toward committing when it shouldn't.
Workflow
- Scope the target: usually
HEAD, sometimes a short unpushed range, or a late change the human decided to commit. - Read the change (
git show --stat,git diff), then the commit convention the repository documents (AGENTS.md,CONTRIBUTING.md, or its equivalent) and the log it describes:git log -20andgit log -5 -- <changed-paths>, bodies as well as subjects. Read them on every run, before drafting; a convention remembered from another repository or an earlier session is not a reading. - Resolve mixed logs in this order: documented project rules, nearby commits touching the same area, then same-author commits within that convention. Do not average incompatible styles or let one author's habits override the repo. If no convention is documented, report the one the sample shows (subject form, scope, language, body shape) and propose it for the contributor guide as a separate change the human commits.
- Rewrite to the commit-economy below: keep durable handoff facts, fold supporting edits into the change they serve, and cut what the diff or tag already proves. Give trivia no bullet of its own. Then set the draft beside the nearest non-target commits of the same type, fix every difference in form, and run the repository's message checker if it has one.
- Rebuild with the bundled script, run from this skill's folder (
scripts/rebuild.mjs), never withgit rebase: rebase makes you the committer of every commit and restamps each committer date to now, and--committer-date-is-author-dateerases the gap between the two dates instead. Write each new message to<dir>/<full-sha>.txt, then runnode scripts/rebuild.mjs messages --repo <path> --base <commit> --messages <dir>with--basethe parent of the oldest target,HEAD~1for your own tip. Input: the linear range<base>..HEADof the checked-out branch and the message files. Output: JSON with the old tip (old), the new tip (new), the old-to-new id map (map) and the signing outcome (signing). It rebuilds every commit in the range oldest first withgit commit-treeon its own tree, the new message where a file names it and its own message elsewhere, under that commit's own author and committer names, emails and raw dates, adding-Sonly where the committer is the repository'suser.email, and leaves a commit that changed nothing under its old id. It moves no ref. Exit 0 means built, 1 means a git call failed, 2 means a usage error or refused input: a merge in range, a--basethat is not an ancestor ofHEAD, or a message file naming a commit outside the range.signingreadingunavailablemeansuser.signingkeyis unset and your commits came out unsigned; stop and fix signing before moving the branch. - Place a late commit by time. Date it at the newest modification time among the files it changes, read before a stash, checkout, or rebase rewrites them; if those times were already reset, ask the human for the time. Once the late change is committed on the branch, run
node scripts/rebuild.mjs place --repo <path> --base <commit> --late <commit> --date "<unix-seconds> <+zone>"with--baseolder than every commit it may pass. Input: the range, the late commit and its time. Output: the same JSON plus the new id of the placed commit (placed). It builds the late commit on the last commit dated at or before--date, its own diff replayed there withgit merge-tree --write-tree --merge-base=<old-parent> <new-parent> <commit>, sets both its dates to--date, and rebuilds every later commit as in step 5 on the tree its own diff makes over its new parent. It moves no ref. Exit codes are as in step 5, and a diff that does not apply at the new point is exit 1. - Verify (below), then move the branch as its own step: only after
verifyexits 0, and for a pushed or shared range only after the human confirms the rewrite, rungit update-ref refs/heads/<branch> <new-tip> <old-tip>, which refuses if the branch moved since the old tip was read. For each rewritten remote ref, push with--force-with-lease=<ref>:<id the mirror was cut at>, never bare--forceor--mirror. If the lease fails, carry only commits that landed after the cut onto the rewritten tip withgit rebase --onto <rewritten tip> <cut id> <remote ref>, re-sign and lease again; do not recut the mirror. Name the cut id in the report.
Rules
- Never create or suggest a commit.
re0-gitworks only on commits the human already decided: rewriting a message or placing a late commit. Using it is never a reason to commit. - Content stays put: a message rewrite keeps the tree byte-identical (
git diff <old> <new>empty); a placed late commit carries exactly its own diff, and every later commit keeps its own. Never edit content in are0-gitpass. - commit-economy: use one bullet per real, durable change, folding in supporting edits. Omit what the diff or version already proves and every co-author tag except a closing
Co-authored-bytrailer that credits a human contributor on a squashed or carried contribution. Match the local log's sampled shape. If none is settled, use a subject line, a blank line, then one-bullet per change on a single unwrapped line, never prose paragraphs. A required checklist step, such as registering a new skill or syncing translations after a source edit, proves the process ran. Fold it into the bullet it serves as a trailing clause, or omit it if that bullet already implies it. Give it a separate bullet only when how it was done is itself non-obvious. This standard also governs first drafts;re0-gitenforces it on existing messages that have drifted. - Original dates and people; signed. A rewritten commit keeps its author, its committer and both of their dates,
HEADincluded: a message edit changes neither when the work was done nor when it landed, so never restamp the past. A gap between the two dates records a rebase, a cherry-pick or a later push and is not a defect; no check reads it, and no commit is rewritten or moved to close one. A late commit takes the time its work was done as both dates. Sign every commit you are the committer of; one someone else committed stays theirs and unsigned, since your signature would claim it. - Linear. Never create a merge commit. A late commit goes where its time falls, and every other commit keeps its place.
- Never rewrite pushed or shared history without explicit confirmation; it forces a force-push. Placing a late commit behind a pushed commit is such a rewrite.
Verification
- Run
node scripts/rebuild.mjs verify --repo <path> --old <old-tip> --new <new-tip> [--placed <new-sha>...], passing each idplaceprinted underplaced. Input: the two tips and the placed commits. Output: JSON withok, achecksentry per check below and each named failure underfailures. Exit 0 means every check passed, 1 means a named failure, 2 a usage error or an id outside the new range. Its first check: the two tips' trees are equal, or differ by exactly the diffs of placed commits that were not in the old range. - The
%an %ae %ad %cn %ce %cdline of every commit in the old range appears unchanged and in order over the new range, the placed commits aside; each placed commit carries one time as both dates; and each commit the repository user committed shows%G?=G. Withoutuser.signingkeythe script reports signingunavailableand lists those commits underunsigned: that is a failure to fix before the branch moves, never a pass. - The new range holds no merge commit, and each placed commit is dated no earlier than its parent's committer date.
- The documented convention and the sampled log were read on this run, each message matches the nearest same-type commits in form, and any repository message checker passes.
- Re-read
git logwith the diff hidden. Restore any cut line needed to follow the change.