## Optional history cleanup after reviewing the source edits

A normal PR only fixes the current branch tip. Do not run a force-push automatically
on merge. Coordinate a write freeze, close or finish open PRs, and rotate exposed
credentials first. Rewriting changes commit IDs and removes commit/tag signatures;
keep author/committer identity and dates unchanged unless separately authorized.

Install git-filter-repo >= 2.47. In a private directory outside any repository,
create a mode-600 file named replacements.txt containing one reviewed literal rule
per line: literal:ORIGINAL_VALUE==>SAFE_REPLACEMENT. Never commit this file, log its
contents, or upload it as a workflow artifact. Use only context-independent
replacements: a runtime credential may need different code changes in older
versions. Do not blindly replace a secret with an environment-variable expression
in every language. Review affected versions and run their tests.

Run these preparation commands in a new private directory (replace OWNER/REPO):

~~~sh
umask 077
git clone --mirror https://github.com/OWNER/REPO.git cleanup.git
cd cleanup.git
git bundle create ../before-cleanup.bundle --all
git for-each-ref --format='%(refname) %(objectname)' refs/heads refs/tags > ../before-refs.txt
git filter-repo --sensitive-data-removal --replace-text ../replacements.txt --replace-message ../replacements.txt
~~~

This processes fetched branch/tag histories and commit/tag messages. Metadata,
binary assets, LFS, releases, Actions artifacts, forks and other clones require
separate inspection. To remove an entire sensitive transcript/file, add
--invert-paths --path PATH (including every historical name) only after confirming
the file is not required. Do not use path removal for needed application source.
The backup bundle still contains PII: restrict access and dispose of it according
to your retention policy after verification.

Before publishing, inspect filter-repo/changed-refs, rescan all rewritten refs,
compare branch tips, and build/test every supported branch. Check that no remote
branch or tag changed since before-refs.txt; restart preparation if any did. There
is no guarantee that a generic replacement preserves every historical program.

After review, publish each approved branch/tag with an explicit expected-old-SHA
lease (replace REF and OLD_SHA using before-refs.txt):

~~~sh
git push --atomic --force-with-lease=REF:OLD_SHA https://github.com/OWNER/REPO.git REF:REF
~~~

Repeat for every affected branch and tag, or supply all corresponding leases and
refspecs in one atomic push. Do not use an unqualified force mirror push: it can
overwrite concurrent work or delete remote refs. Protected refs may require an
owner-approved temporary configuration change. GitHub pull-request refs are
read-only; contact GitHub Support for sensitive cached views/PR refs and LFS
purging. Collaborators must re-clone or carefully rebase their work so old history
is not reintroduced. Confirm every intended remote ref matches the rewritten SHA.

For a vendor export, keep the complete filter-repo/commit-map and the original PR
snapshot in your private workspace. Use CodeMerchant's scripts/export-redacted-prs.mjs
command (docs/redacted-pr-export.md) to package the reviewed redacted mirror and
remap PR base/head/merge references and commit lists. It regenerates patches and
blocks missing mappings. Never pair rewritten Git history with cached original
PR patches or unredacted PR prose. Export integrity does not certify PII removal.

A clean current branch or merged redaction PR does not prove complete removal. Old commits can remain in GitHub’s read-only PR references, cached views, other branches, tags, forks and clones.

For a reviewed history rewrite, retain git-filter-repo’s commit-map and changed-refs, map old commits to their replacements, and identify affected PR numbers and First Changed Commit(s). Repository owners cannot overwrite refs/pull/*, even with a force push. Coordinate branch/tag and fork cleanup, then ask GitHub Support to dereference affected PRs and purge cached views. Rebase or reclone collaborators’ copies to avoid restoring old history. Rotate exposed credentials.

Reference: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/removing-sensitive-data-from-a-repository
