Change git email for previous commits

17,280

Solution 1

You can indeed do his for many commits at once like this:

git rebase -i HEAD~40 -x "git commit --amend --author 'Author Name <[email protected]>' --no-edit"

I worked this out better in this answer.

Solution 2

As you mentioned in your question (the link to the answer you found), this is the script indeed.

Note:

filter-branch is doing a rebase (will rewrite the history of the branch) which means that everyone who had a copy of the branch will have to delete and checkout it again.


The script origin is from here - Git-Tools-Rewriting-History:

# Loop over all the commits and use the --commit-filter
# to change only the email addresses

git filter-branch --commit-filter '

    # check to see if the committer (email is the desired one)
    if [ "$GIT_COMMITTER_EMAIL" = "<Old Email>" ];
    then
            # Set the new desired name
            GIT_COMMITTER_NAME="<New Name>";
            GIT_AUTHOR_NAME="<New Name>";

            # Set the new desired email
            GIT_COMMITTER_EMAIL="<New Email>";
            GIT_AUTHOR_EMAIL="<New Email>";

            # (re) commit with the updated information
            git commit-tree "$@";
    else
            # No need to update so commit as is
            git commit-tree "$@";
    fi' 
HEAD

What does the script do?

Its looping over all your commits and once you find match its replacing the name and email of the committer.

Solution 3

Here's a version based on Chris Maes' answer that only applies the change to commits with a matching email address, and uses rebase --root (since git 1.7) to write from the beginning of your history.

If you want to choose the a specific base commit, you'll want to remove --root, and use the refspec you want.

function reauthor_all {
  if [[ "$#" -eq 0 ]]; then
    echo "Incorrect usage, no email given, usage is: $FUNCNAME <email>" 1>&2
    return 1
  fi

  local old_email="$1"

  # Based on
  # SO: https://stackoverflow.com/a/34863275/9238801

  local new_email="$(git config --get user.email)"
  local new_name="$(git config --get user.name)"

  # get each commit's email address ( https://stackoverflow.com/a/58635589/9238801 )
  # I've broken this up into two statements and concatenated
  # because I want to delay evaluation

  local command='[[ "$(git log -1 --pretty=format:'%ae')" =='
  command+=" '$old_email' ]] && git commit --amend --author '$new_name <$new_email>' --no-edit || true"


  git rebase -i --root -x "$command"
}

Use on my own repo:

reauthor_all "[email protected]"
hint: Waiting for your editor to close the file... 
Press ENTER or type command to continue
Executing: [[ "$(git log -1 --pretty=format:%ae)" == '[email protected]' ]] && git commit --amend --author 'Matthew Strasiotto <[email protected]>' --no-edit || true
Executing: [[ "$(git log -1 --pretty=format:%ae)" == '[email protected]' ]] && git commit --amend --author 'Matthew Strasiotto <[email protected]>' --no-edit || true
[detached HEAD 1e281b5] First Message
...etc

You'll need to force push when it looks right eventually, and this WILL change commit shas, so that's going to cause a whole host of other problems.

Share:
17,280
Kevin Cohen
Author by

Kevin Cohen

Updated on June 27, 2022

Comments

  • Kevin Cohen
    Kevin Cohen almost 2 years

    So I read a lot about how to change previous commit's email address but for some reason mine is not updating.

    I did like 40 commits to my private repo with my local email ([email protected]) which is bad since this email is not associated(and it can't be) with github.

    I then remembered that I needed to set the git.config before and so I did:

     git config user.email "[email protected]"
    

    and did a test commit and it worked perfectly.

    Is there a way I can revert all my previous commits to this new email?

    I read this question on SO Change the author and committer name and e-mail of multiple commits in Git and used this

     git filter-branch -f --env-filter "                         
                        GIT_AUTHOR_EMAIL='[email protected]'; 
                        GIT_COMMITTER_EMAIL='[email protected]';
                        " 
                    HEAD
    

    But it DID NOT work... I can still see the email of my previous commits with the .patch extension as the .local email address

  • Kevin Cohen
    Kevin Cohen over 8 years
    I did this, but when I view my past commits, it is still showing as my local email address... any ideas why?
  • CodeWizard
    CodeWizard over 8 years
    Where do you see your email? on the same branch or is it on a different branch?
  • Kevin Cohen
    Kevin Cohen over 8 years
    Same branch.. For some reason I did it then I pushed and what it happened is that it duplicated all of my commits again with the new email, BUT, still doesn't show in the contributions calendar which is the whole point of this question
  • CodeWizard
    CodeWizard over 8 years
    I didn't understood what happened. can you provide screen shoot?
  • Jonah
    Jonah about 4 years
    and then git push --force?
  • Chris Maes
    Chris Maes about 4 years
    since this rewrites your commits, yes. Consider using git push --force-with-lease to make sure not to crush work from your collegues.
  • ravi
    ravi over 3 years
    This is exactly what I was looking for. Thank you :)
  • Matthew Strasiotto
    Matthew Strasiotto about 3 years
    A note: I use string concatenation to delay the evaluation of certain parts of the command, as can been seen in the output. This feels like an ugly hack, but appears to be the most portable ugly hack- Newer version of bash (>= 4.4)seem to support ${param@Q} for delaying evaluation, but if you're on OSX, you'll start with 3.2, & I've found solutions that abstract manual \` escaping into bash functions, but rebase -x 'function_in_bashrc'` wont find function_in_bashrc. I mean, maybe there's no such thing as a bash script that doesn't include an ugly hack
  • Matthew Strasiotto
    Matthew Strasiotto about 3 years
    If anyone has better ideas for delaying evaluation of parameter substitution/shell expansion, please weigh in
  • Oscar Andersson
    Oscar Andersson over 2 years
    Thanks Chris Maes! :) For anyone else using this, please make sure to change HEAD~40 to however many commits you want to affect. Read more at git-scm.com/book/en/v2/Git-Tools-Rewriting-History
  • Ajay G.
    Ajay G. over 2 years
    Works like a charm!
  • keypoint
    keypoint over 2 years
    works for me! thanks!
  • sshine
    sshine about 2 years
    @ChrisMaes: Please note that git commit --amend --author ... does not change the committer, only the author! So while it may appear that your email was changed, there is, in fact, metadata in the repository that says who the old committer is. While the filter-branch (or filter-repo) methods are more crude, they actually change both. Proof: curl -s https://api.github.com/repos/sshine/author-committer/commits | jq '.[0].commit | { author, committer }' -- I did a git commit --amend --author="John Doe ..." here, and you can see that the committer is not John Doe.