History surgery
Rewriting history is the operation people reach for git filter-repo for, run once every two years, and get wrong. torii ships the whole set as first-class subcommands built on one tree-rewriting engine, with the same three guarantees on every one of them: a safety snapshot before the first commit is touched, author and committer dates preserved by default, and a refusal to start on a dirty tree or a pending operation.
The guarantees
Every command on this page takes a snapshot first. If the result is wrong:
torii snapshot list
torii snapshot restore <id>Pass --dry-run to see what would change without changing it, --since <ref> to bound the rewrite to a range, and --no-snapshot if you have your own backup and want the speed.
GPG signatures do not survive a rewrite — the commit object changes, so the signature over it no longer verifies. Re-sign afterwards with torii sign.
Messages
torii history reword <hash> -m "fix: the message it should have had"
torii history reword <hash> -F message.txt
torii history reword --map rewrites.txt # one "<hash> <message>" per lineContent, author, committer and dates are untouched. This is the non-interactive path that previously forced git filter-repo.
Identity
torii history reauthor --old "Old Name <old@example.com>" --new "New <new@example.com>"
torii history reauthor --old old@example.com --new "New <new@example.com>" --committer
torii history mailmap apply
torii history mailmap apply --file other.mailmap --dry-runAnnotated tags are rewritten too, so a tagger identity does not survive as the only trace of the old name.
Dates
torii history redate <hash> --date "2026-01-01T09:00:00+01:00"
torii history redate --map dates.txt
torii history rewrite "2026-01-01" "2026-03-01" # shift a whole rangeContent
torii history replace-text --literal 'OLD==>NEW'
torii history replace-text --regex 'AKIA[0-9A-Z]{16}==>***REMOVED***'
torii history replace-text --rules rules.txt --paths src
torii history replace-text --redact-secrets--redact-secrets redacts every line the built-in scanner flags, which is the fastest way to clean a repository after a key has been committed. Rotate the key anyway: it was public the moment it was pushed.
Paths
torii history filter-path --keep src --keep Cargo.toml
torii history filter-path --remove vendor
torii history filter-path --subdirectory crates/torii # promote a subdir to the root
torii history filter-path --rename old/path:new/path
torii history remove-file secrets.env # purge one file entirelyAdd --prune-empty to drop commits that become empty once their only changes are gone.
Anything else
torii history exec-filter 'cargo fmt --all'Runs a command against each commit's materialised tree — the classic filter-branch --tree-filter, without the twenty lines of shell around it.
After a rewrite
The rewrite is local. Everyone else still has the old history, and the next push has to be a force push:
torii sync --forceAnyone who had the old branch checked out needs to reset onto the new one. On a shared branch, agree on the rewrite before you run it, not after.