Change git email for previous commits
Asked Answered
M

3

46

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 How do I change the author and committer name/email for multiple commits? 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

Mourant answered 18/1, 2016 at 9:5 Comment(2)
I believe you are going to have to rewrite the history of your branch to change the emails, which seem to appear along with the name of the committer. If you can accept this, then filter-branch or git rebase should do the trick.Danedanegeld
Possible duplicate of How to amend several commits in Git to change authorIntricate
I
84

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.

Intricate answered 18/1, 2016 at 20:13 Comment(5)
and then git push --force?Pecuniary
since this rewrites your commits, yes. Consider using git push --force-with-lease to make sure not to crush work from your collegues.Intricate
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-HistoryInclinable
works for me! thanks!Ironhanded
@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.Tamatave
E
15

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.

Emmerich answered 18/1, 2016 at 9:16 Comment(4)
I did this, but when I view my past commits, it is still showing as my local email address... any ideas why?Mourant
Where do you see your email? on the same branch or is it on a different branch?Emmerich
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 questionMourant
I didn't understood what happened. can you provide screen shoot?Emmerich
L
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://mcmap.net/q/363902/-change-git-email-for-previous-commits

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

  # get each commit's email address ( https://mcmap.net/q/373231/-how-to-get-the-author-of-the-last-commit-in-git )
  # 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.

Lira answered 18/2, 2021 at 8:48 Comment(2)
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 hackLira
If anyone has better ideas for delaying evaluation of parameter substitution/shell expansion, please weigh inLira

© 2022 - 2024 — McMap. All rights reserved.