Git, rewrite previous commit usernames and emails

Git

Git Problem Overview


I've committed a bunch of commits to a project on Github, however I realized I hadn't set up the proper email and committer full name on the computer I'm currently using to make my commits and therefore the users avatar and email address are not there.

How can I rewrite all past commit email and usernames?

Git Solutions


Solution 1 - Git

You can add this alias:

git config --global alias.change-commits '!'"f() { VAR=\$1; OLD=\$2; NEW=\$3; shift 3; git filter-branch --env-filter \"if [[ \\\"\$\`echo \$VAR\`\\\" = '\$OLD' ]]; then export \$VAR='\$NEW'; fi\" \$@; }; f"

To change the author name:

git change-commits GIT_AUTHOR_NAME "old name" "new name"

or the email for only the last 10 commits:

git change-commits GIT_AUTHOR_EMAIL "[email protected]" "[email protected]" HEAD~10..HEAD

Alias:

change-commits="!f() { VAR=$1; OLD=$2; NEW=$3; shift 3; git filter-branch --env-filter \"if [[ \\\"$`echo $VAR`\\\" = '$OLD' ]]; then export $VAR='$NEW'; fi\" \$@; }; f"

Source: https://github.com/brauliobo/gitconfig/blob/master/configs/.gitconfig

Solution 2 - Git

See here:

git filter-branch -f --env-filter \
"GIT_AUTHOR_NAME='Newname'; GIT_AUTHOR_EMAIL='newemail'; \
GIT_COMMITTER_NAME='committed-name'; GIT_COMMITTER_EMAIL='committed-email';" HEAD

Solution 3 - Git

If you have already pushed some of your commits to the public repository, you do not want to do this, or it would make an alternate version of the master's history that others may have used. "Don't cross the streams... It would be bad..."

That said, if it is only the commits you have made to your local repository, then by all means fix this before you push up to the server. You can use the git filter-branch command with the --commit-filter option, so it only edits commits which match your incorrect info, like this:

git filter-branch --commit-filter '
      if [ "$GIT_AUTHOR_EMAIL" = "wrong_email@wrong_host.local" ];
      then
              GIT_AUTHOR_NAME="Your Name Here (In Lights)";
              GIT_AUTHOR_EMAIL="correct_email@correct_host.com";
              git commit-tree "$@";
      else
              git commit-tree "$@";
      fi' HEAD

Solution 4 - Git

After applying Olivier Verdier's answer:

git filter-branch -f --env-filter \
"GIT_AUTHOR_NAME='Newname'; GIT_AUTHOR_EMAIL='newemail'; \
GIT_COMMITTER_NAME='committed-name'; GIT_COMMITTER_EMAIL='committed-email';" HEAD

...to push the changed history on the original repository use:

git push origin +yourbranch

The above command (note the plus) forces rewriting the history on the original repo as well. Use with caution!

Again, WARNING: this will make ALL commits as committed by Newname/newemail! The scenario is where you have a repo with only one author who committed using different identities by mistake and you want to fix it.

Solution 5 - Git

https://help.github.jp/enterprise/2.11/user/articles/changing-author-info/

#!/bin/sh

git filter-branch --env-filter '

OLD_EMAIL="[email protected]"
CORRECT_NAME="yourName"
CORRECT_EMAIL="yourEmail"

if [ "$GIT_COMMITTER_EMAIL" = "$OLD_EMAIL" ]
then
    export GIT_COMMITTER_NAME="$CORRECT_NAME"
    export GIT_COMMITTER_EMAIL="$CORRECT_EMAIL"
fi
if [ "$GIT_AUTHOR_EMAIL" = "$OLD_EMAIL" ]
then
    export GIT_AUTHOR_NAME="$CORRECT_NAME"
    export GIT_AUTHOR_EMAIL="$CORRECT_EMAIL"
fi
' --tag-name-filter cat -- --branches --tags

this totally worked for me. After git push, make sure to see update on git's web portal. If the commit was still not linked to my account, shown default thumbnail image next to the commit and it was not reflected on my contributions timeline chart, go to the commit url and append .patch at the end of the url, and verify the name and email are correct.

Solution 6 - Git

Considering use of git-filter-branch is not desired, to do the same thing in git-filter-repo (you may need to install it first with pip install git-filter-repo):

git-filter-repo --name-callback 'return name.replace(b"OldName", b"NewName")' --email-callback 'return email.replace(b"old@email.com", b"[email protected]")'

If repository is original, w/o remote, you will have to add --force to force rewrite. (You may want to create backup of your repo before doing this.)

If you do not want to preserve refs (they will be displayed in branch history of Git GUI), you will have to add --replace-refs delete-no-add.

For more advanced features, see "Filtering of names & emails".

P.S. Stolen and improved from https://stackoverflow.com/a/59591928/714907.

Solution 7 - Git

For those that just want the easy copy paste version (aside from updating emails and names):

git config alias.change-commits '!'"f() { VAR=\$1; OLD=\$2; NEW=\$3; shift 3; git filter-branch --env-filter \"if [[ \\\"\$\`echo \$VAR\`\\\" = '\$OLD' ]]; then export \$VAR='\$NEW'; fi\" \$@; }; f "
git change-commits GIT_AUTHOR_NAME "<Old Name>" "<New Name>" -f
git change-commits GIT_AUTHOR_EMAIL <old@email.com> <new@email.com> -f
git change-commits GIT_COMMITTER_NAME "<Old Name>" "<New Name>" -f
git change-commits GIT_COMMITTER_EMAIL <old@email.com> <new@email.com> -f

Solution 8 - Git

The answers already present are complete. But are you sure, you need those? For eg. I was facing a similar issue but the answers here were overkill for that case. My case and the solution are described below:

Assume you have two email ids, [email protected] and [email protected]. It is possible that the previous commits were through [email protected] which is not the email id that you want. In that case, one option is to simply link [email protected] to your GitHub account.

How to do it?

Find the option to add the email in the Emails section on the settings page.

enter image description here

Still lost?

The first three steps mentioned on the github page will be enough.

NOTE:
  1. Github supports multiple email ids for a single github account.
  2. Since you are not replacing the email id, but just adding a new one, commits through both the email ids are linked to your Github account.
  3. It's not necessary that [email protected] should be set as primary email id.

Solution 9 - Git

An alternative to rewriting the history, if you mainly care about the local repo display names, is the .mailmap file, which is basically a list of names and emails. For example, placing this in a .mailmap file in the root of a repo:

Tamika Page <tamika@somejob.com>
Orlando Cervantes <orlando.cervantes@otherjob.com> Orlando Jackson <orlando.jackson@otherjob.com>
Jared Michael <jared.michael@gmail.com> <jared@desktop.(none)>

will result in any commits attributed to [email protected] being shown with the name Tamika Page, regardless of the Committer Name, commits attributed to Orlando Jackson <[email protected]> being displayed as Orlando Cervantes, and the pesky <jared@desktop.(none)> commits being attributed to [email protected]. For full details, check out the git documentation for this feature - since it is built into git it should work for any reasonably new git client.

There's a big caveat here though: while it's been supported for quite a while in the official git client, support in various git implementations, notably the big web interfaces, isn't guaranteed - see this question, where consensus on whether GitHub respects it is mixed but seems negative. I threw together quick test repos on GitHub and GitLab and neither seem to pay attention to .mailmap, unfortunately.

As mentioned in @paradocslover's answer, the services have their own interfaces to do similar things, but you have to set that up per-service, and it won't affect your local copy at all. Because .mailmap is part of the repo, it will work locally for anyone who clones your repo (you can clone the repos linked above to see for yourself), but it seems it won't show in the web interfaces I tested.

For some cases you do want to rewrite the history, of course, but that can be rather invasive and comes with all the standard caveats, so for some situations it's nice to have this option, which may be sufficient, especially if rewriting isn't practical.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJP SilvashyView Question on Stackoverflow
Solution 1 - GitbraulioboView Answer on Stackoverflow
Solution 2 - GitOlivier VerdierView Answer on Stackoverflow
Solution 3 - GitewallView Answer on Stackoverflow
Solution 4 - GitsarussoView Answer on Stackoverflow
Solution 5 - GitJacccckView Answer on Stackoverflow
Solution 6 - GitPugsleyView Answer on Stackoverflow
Solution 7 - GitNick KuzniaView Answer on Stackoverflow
Solution 8 - GitparadocsloverView Answer on Stackoverflow
Solution 9 - GitcincodenadaView Answer on Stackoverflow