Masking Email Addresses in Mercurial Commit Logs

The commit log glowed red with a mistake. An email address sat in plain text, stamped into history. You can’t rewrite every developer’s memory. But you can stop it from happening again.

Masking email addresses in logs for Mercurial is not optional. It’s a safeguard against leaking personal data in a repository that lives forever. Mercurial stores author and committer information in changesets. By default, that includes the full email address. Once pushed, it spreads to every clone.

To mask email addresses, configure Mercurial to sanitize before commit. Use the [hooks] section in your .hgrc file to run a pre-commit script. This script can parse HGUSER and replace the email part with a placeholder or hashed value. Example:

[hooks]
precommit.maskemail = python:/path/to/mask_email.py

mask_email.py would inspect environment variables and commit metadata, replace username@example.com with username@masked, and ensure that change propagates to the commit object before it’s written.

For server-side protection, use a pretxnchangegroup hook. This intercepts incoming changesets before they land in the central repo. It’s an effective gate for teams, enforcing masking at the boundary. Example:

[hooks]
pretxnchangegroup.maskemail = python:/path/to/server_mask_email.py

Pattern matching with regex is the fastest route. Target [A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,} inside commit metadata and replace. Done right, the masking is invisible to developers who commit, but airtight in the logs.

A common mistake is to rely on hg convert to rewrite history after the fact. That’s expensive and messy. Prevention at commit time keeps your repository clean and compliant with privacy regulations.

Version control is a record of decisions. Masking email addresses ensures those decisions aren’t chained to identities in a way that violates policy or law.

Want to see masked commits in Mercurial without writing boilerplate scripts? Check out hoop.dev and get it running in minutes.