Skip to content

Instantly share code, notes, and snippets.

@paladini
Created July 19, 2025 17:39
Show Gist options
  • Save paladini/222d09c7cfb13d1952e4ba66f677c58e to your computer and use it in GitHub Desktop.
Save paladini/222d09c7cfb13d1952e4ba66f677c58e to your computer and use it in GitHub Desktop.
This script will automatically find your global name/email, detect the old emails in your repository's log, and ask you which one you want to replace before rewriting the history. Be very careful with this command. Read the first comment too.
#!/bin/bash
# A script to rewrite author/committer history for a Git repository.
# It uses 'git filter-branch' and has no external dependencies.
# Created by @paladini - github.com/paladini
# Define colors for output
C_BLUE="\033[1;34m"
C_GREEN="\033[1;32m"
C_RED="\033[1;31m"
C_YELLOW="\033[1;33m"
C_RESET="\033[0m"
# --- 1. Get New Author Information ---
echo -e "${C_BLUE}--- Step 1: Fetching your global Git configuration ---${C_RESET}"
NEW_NAME=$(git config --global user.name)
NEW_EMAIL=$(git config --global user.email)
if [ -z "$NEW_NAME" ] || [ -z "$NEW_EMAIL" ]; then
echo -e "${C_RED}Error: Your global user.name and user.email are not set.${C_RESET}"
echo "Please set them first with:"
echo " git config --global user.name \"Your Name\""
echo " git config --global user.email \"[email protected]\""
exit 1
fi
echo "Your configured identity is: ${C_GREEN}${NEW_NAME} <${NEW_EMAIL}>${C_RESET}"
echo
# --- 2. Find and Select Old Email ---
echo -e "${C_BLUE}--- Step 2: Finding all unique author emails in the log ---${C_RESET}"
# Get a sorted, unique list of author emails from the entire history
OLD_EMAILS=($(git log --all --format='%ae' | sort -u))
if [ ${#OLD_EMAILS[@]} -eq 0 ]; then
echo -e "${C_YELLOW}No commits found in this repository. Nothing to do.${C_RESET}"
exit 0
fi
# Let user choose which email to replace
echo "Please choose the OLD email you want to replace:"
select OLD_EMAIL in "${OLD_EMAILS[@]}"; do
if [[ -n "$OLD_EMAIL" ]]; then
break
else
echo -e "${C_RED}Invalid selection. Please try again.${C_RESET}"
fi
done
if [ "$OLD_EMAIL" == "$NEW_EMAIL" ]; then
echo -e "${C_YELLOW}The old email is the same as the new email. Nothing to do.${C_RESET}"
exit 0
fi
echo
echo -e "You will replace commits from: ${C_RED}${OLD_EMAIL}${C_RESET}"
echo
# --- 3. Final Confirmation ---
echo -e "${C_BLUE}--- Step 3: Confirmation ---${C_RESET}"
echo -e "${C_YELLOW}WARNING: This will rewrite your project's history. This is a destructive operation.${C_RESET}"
echo
echo "The following change will be applied to all matching commits:"
echo -e " - FROM: ${C_RED}${OLD_EMAIL}${C_RESET}"
echo -e " - TO: ${C_GREEN}${NEW_NAME} <${NEW_EMAIL}>${C_RESET}"
echo
read -p "Are you absolutely sure you want to proceed? (y/N) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo "Operation cancelled."
exit 1
fi
# --- 4. Execute History Rewrite ---
echo
echo -e "${C_BLUE}--- Step 4: Rewriting history... (This may take a while) ---${C_RESET}"
# Export variables so they are available in the subshell created by filter-branch
export OLD_EMAIL
export NEW_NAME
export NEW_EMAIL
git filter-branch --env-filter '
if [ "$GIT_COMMITTER_EMAIL" = "$OLD_EMAIL" ]; then
export GIT_COMMITTER_NAME="$NEW_NAME"
export GIT_COMMITTER_EMAIL="$NEW_EMAIL"
fi
if [ "$GIT_AUTHOR_EMAIL" = "$OLD_EMAIL" ]; then
export GIT_AUTHOR_NAME="$NEW_NAME"
export GIT_AUTHOR_EMAIL="$NEW_EMAIL"
fi
' --tag-name-filter cat -- --all
# --- 5. Clean Up and Final Instructions ---
echo
echo -e "${C_GREEN}History rewritten successfully!${C_RESET}"
echo
echo -e "${C_BLUE}--- Step 5: Final Instructions ---${C_RESET}"
echo "Git keeps a backup of your old history in 'refs/original/'."
read -p "Do you want to remove this backup now? (y/N) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin
echo "Backup refs removed."
fi
echo
echo -e "${C_YELLOW}IMPORTANT: To make these changes permanent on your remote, you must force-push.${C_RESET}"
echo "Run the following command for your main branch:"
echo -e "${C_GREEN}git push --force origin main${C_RESET}"
@paladini
Copy link
Author

How to Use

  1. Save the Script: Save the code for the script into a file named git-rewrite-author.sh in the root of your Git repository.

  2. Make it Executable: Open your terminal and grant execution permissions to the script:

    chmod +x git-rewrite-author.sh
  3. Run the Script: Execute the script from within your repository. It will guide you through the process.

    ./git-rewrite-author.sh

⚠️ Critical Warning

Rewriting history changes the unique ID (SHA-1 hash) of every altered commit. After the script finishes, your local history will be different from the remote repository's history. To update the remote, you must force-push.

This is a destructive action. If you are collaborating with others on this branch, a force-push can create significant problems for their work. Ensure you are the only one working on the branch or that your entire team is coordinated before proceeding.

# Example: Force-push your changes to the 'main' branch on 'origin'
git push --force origin main

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment