Kevin Cohen
Kevin Cohen

Reputation: 1341

Change git email for previous commits

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

Upvotes: 47

Views: 31201

Answers (3)

Matthew Strasiotto
Matthew Strasiotto

Reputation: 369

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.

Upvotes: 3

Chris Maes
Chris Maes

Reputation: 37722

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.

Upvotes: 88

CodeWizard
CodeWizard

Reputation: 142004

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.

Upvotes: 15

Related Questions