What happens when you rewrite history
Rewriting history is the operation people reach for once every two years, run from a half-remembered git filter-branch incantation, and get wrong. The command…
Rewriting history is the operation people reach for once every two years, run from a half-remembered git filter-branch incantation, and get wrong. The command is unfamiliar precisely because it is rare, and it is destructive precisely when it is unfamiliar.
Since 0.11 and 0.12 the whole surface is first-class subcommands of torii history, and all of them are the same engine underneath: reword changes messages, reauthor changes identities, redate changes dates, replace-text changes file contents, filter-path changes which paths exist, and exec-filter runs whatever you like against each materialised tree.
The four things that happen before a commit is touched
It refuses to start on a dirty tree. A rewrite walks and rebuilds every commit in range; doing that with uncommitted work in the way means the work is neither in the old history nor the new one. The pre-flight also refuses when an operation is pending — a rebase halfway through, a cherry-pick waiting on a conflict — because the rewrite would be built on a state you are still deciding.
It takes a snapshot. Not a commit, not a stash: a local save of the working tree, restorable by id, that never enters your history and never reaches a remote. This is the whole difference between "the rewrite went wrong" and "the rewrite went wrong and I have lost the afternoon".
torii snapshot list
torii snapshot restore <id>It preserves dates. Author and committer dates survive by default. That sounds like a detail until you have watched a filter-branch flatten six months of history into "all committed thirty seconds ago", and with it every signal about how the project actually grew.
It rewrites the tree, then moves the refs. The commits are rebuilt first and the references are pointed at the new history afterwards, so an interrupted rewrite leaves the old refs intact rather than half-moved.
What it deliberately does not hide
Two consequences are inherent to rewriting history, and pretending otherwise would be worse than saying them:
Signatures do not survive. A GPG signature signs a commit object. Rewriting produces a different object, so the signature no longer verifies — it is not stripped as a courtesy, it is simply no longer true. torii sign re-signs the new history when you want it back.
The next push is a force push. Everyone else still has the old history. On a shared branch, that is a conversation to have before the rewrite, not after: torii sync --force does what it says, and what it says is that your version wins.
The one that matters most
torii history replace-text --redact-secretsIt redacts every line the built-in scanner flags, across every file in every commit. It is the fastest way to clean a repository after a key has been committed — and it does not make the key safe. The key was public the moment it was pushed; rotate it first, then clean the history so the next person cloning does not find it. The order is not negotiable and the tool cannot enforce it for you.
Previewing
Every one of these takes --dry-run, and --since <ref> to bound the range. On a repository whose history matters, the sequence that has never let anyone down is: dry run, read the output, snapshot, run it, check torii log, and only then force-push.