Docs

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.

pre-flight dirty tree? stop snapshot taken by default rewrite the tree dates preserved refs and working tree moved to the new history torii snapshot restore <id> if the result is wrong signatures do not survive a rewrite (re-sign with torii sign) · the push that follows is a force push

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 line

Content, 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-run

Annotated 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 range

Content

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 entirely

Add --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 --force

Anyone 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.