Skip to content

Cold-FR/git-mailmask

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

22 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

git-mailmask

Rewrite your Git commit history to replace exposed email addresses with your GitHub noreply address β€” across one or multiple repositories, interactively.


Overview

git-mailmask is an interactive CLI tool available for Linux/macOS (Bash) and Windows (PowerShell). It uses git-filter-repo under the hood to rewrite commit history and replace one or more old email addresses with a new identity β€” typically a GitHub privacy-safe noreply address (<id>+<username>@users.noreply.github.com).

This is useful when you have accidentally committed with a personal or work email and want to retroactively anonymize your public commit history.


Demo of git-mailmask in action, showing the interactive prompts and repository selection

Features

  • πŸ” Rewrites full Git history across all branches
  • πŸ“‹ Supports multiple old emails in a single run
  • πŸ™ Optional GitHub CLI integration to auto-fill your identity and browse your repositories
  • βœ… Interactive menus β€” arrow keys, space to select, enter to confirm
  • πŸ“„ Paginated multi-select for large repository lists
  • πŸ–₯️ Cross-platform: Bash (Linux/macOS) and PowerShell (Windows)
  • πŸ“ Supports local repositories β€” work on an already-cloned repo or the current directory
  • πŸš€ --auto-push flag to skip the push confirmation prompt

Requirements

All platforms

pip install git-filter-repo

Windows users: Python and pip may not be installed by default. See the official Python installation guide to get started.

Optional (recommended)

  • GitHub CLI (gh) β€” enables auto-detection of your GitHub username/email and lets you browse and select repositories directly from your account.
# macOS
brew install gh

# Windows (winget)
winget install --id GitHub.cli

# Linux
sudo apt install gh  # Debian/Ubuntu

Quick Install

Linux / macOS

curl -sSL https://raw.githubusercontent.com/Cold-FR/git-mailmask/main/git_mailmask.sh -o git_mailmask.sh && chmod +x git_mailmask.sh

Windows (PowerShell)

Invoke-WebRequest -Uri "https://raw.githubusercontent.com/Cold-FR/git-mailmask/main/git_mailmask.ps1" -OutFile "git_mailmask.ps1"

Installation

Clone or download the scripts, then make the Bash script executable:

git clone https://github.com/your-username/git-mailmask.git
cd git-mailmask
chmod +x git_mailmask.sh

Usage

Linux / macOS

./git_mailmask.sh

To skip the push confirmation at the end:

./git_mailmask.sh --auto-push

Windows

.\git_mailmask.ps1

To skip the push confirmation at the end:

.\git_mailmask.ps1 --auto-push

Note for Windows users: If the script is blocked after download, unblock it first:

Unblock-File .\git_mailmask.ps1

Step-by-Step Walkthrough

1. New Identity

You will be prompted for the replacement name and email to apply to all rewritten commits.

If the GitHub CLI is installed and authenticated, your GitHub username and noreply email are fetched automatically and offered as defaults:

NEW IDENTITY :
- GitHub Username [Enter for: your-username] :
- GitHub Email [Enter for: 12345678+your-username@users.noreply.github.com] :

Press Enter to accept the defaults, or type a custom value.

2. Old Emails to Replace

Enter all email addresses that should be replaced, one per line. Press Enter on an empty line to finish.

OLD EMAILS TO REPLACE :
   (Leave empty and press Enter to finish)
   > old.work@company.com
   > personal@gmail.com
   >

3. Repository Source

Choose how to provide the target repositories:

  (X) Enter a remote repository URL manually
  ( ) Connect to GitHub and select from my repositories
  ( ) Process the current directory (/your/current/path)
  ( ) Enter the path to a local repository manually
  • Remote URL β€” paste a single HTTPS or SSH repository URL. The script clones it, rewrites history, and force-pushes back.
  • GitHub repositories β€” requires the GitHub CLI. Fetches all your repos and displays a paginated multi-select menu. Use arrow keys to navigate, Space to toggle selection, and Enter to confirm.
  • Current directory β€” runs directly on the repo in your working directory, no clone needed.
  • Local path β€” enter or drag-and-drop a path to any local git repository. Quotes are stripped automatically.

4. Cleanup & Push

The tool will:

  1. Clone the repository into a temporary folder (remote mode) or work in place (local mode)
  2. Track all remote branches locally
  3. Apply the mailmap rewrite via git filter-repo
  4. Restore the remote origin (removed by git filter-repo)
  5. Ask whether to force-push β€” or push automatically if --auto-push was passed
  6. Delete the temporary working directory
History successfully rewritten locally!
Do you want to force push to the remote? [Y/n]
=================================================
OPERATION COMPLETED SUCCESSFULLY !
=================================================

How It Works

The script generates a Git mailmap file mapping each old email to the new identity:

Your Name <new@email.com> <old@email.com>

This file is passed to git filter-repo --mailmap, which rewrites every matching commit in the full history β€” including all branches.


⚠️ Important Warnings

  • This rewrites Git history. All commit SHAs will change. This is a destructive, irreversible operation on the remote.
  • Collaborators will need to re-clone or rebase their local copies after a force-push.
  • You must have push access (with force-push allowed) to the target repository.
  • For organization repositories, confirm that force-push is not blocked by branch protection rules.

Resetting a Local Repository After Cleanup

Once git-mailmask has force-pushed rewritten history, any existing local clone will be out of sync. To realign it without re-cloning from scratch:

git fetch origin
git reset --hard origin/main  # replace 'main' with your branch name

If you have multiple branches to reset:

git fetch --all
git reset --hard origin/$(git rev-parse --abbrev-ref HEAD)

Warning: git reset --hard discards all local uncommitted changes. If you have work in progress, you can stash it first:

git stash
# then after the reset:
git stash pop

Example

./git_mailmask.sh

# New identity:
#   Username: johndoe
#   Email:    12345+johndoe@users.noreply.github.com

# Old emails to replace:
#   john.doe@oldcompany.com
#   johndoe@personal.io

# Repository: https://github.com/johndoe/my-project

All commits previously authored or committed with the old emails will be rewritten to johndoe <12345+johndoe@users.noreply.github.com>.


License

MIT Β© Cold-FR

About

Protect your privacy: A cross-platform script to bulk-replace hardcoded emails in Git repositories with GitHub noreply addresses.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors