Skip to main content

Obliterating history from Git

It should not happen often that this is necessary, but it is useful to know.

To obliterate history means removing it from three different sources: Gerrit, Forgejo, and GitHub.

A tool has been written, called gerrit-rewrite-branch, to rewrite Gerrit history completely, including the meta on past CLs.

To use it, build it as --release (it will stack overflow on debug mode), and find the following repos, and make backups of them:

  • /var/lib/gerrit/git/lix.git
  • /var/lib/forgejo/repositories/*/lix.git

To start off, stop Gerrit and find the Git repo for it. The tool requires four things: The email address to obliterate, and a replacement name + email address. It also needs a cutoff date for where to remove commits before. To find this, run git cat-file -p {commit} for a commit earlier than the oldest you want to remove, and note down the timestamp on the committer line.

Call the tool. It will churn for a while, and rewrite all previous Git commits, plus the Gerrit metadata of affected commits. As a bonus, run a git gc --prune=now.

Before turning on Gerrit, run systemd-run -p DynamicUser=yes -p StateDirectory=gerrit -t gerrit reindex -d /var/lib/gerrit. This ensures Gerrit is aware of the changes made outside of its existence.

For forgejo, no special steps are needed; just run the same tool over these repos plus all their forks, and run git gc --prune=now as well.

Once Gerrit and Forgejo are back up, run ssh gerrit.lix.systems replication start --now --url github to propagate the changes to GitHub.