Change git email for previous commits
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.
Kevin Cohen
Updated on June 27, 2022Comments
-
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 over 8 yearsI did this, but when I view my past commits, it is still showing as my local email address... any ideas why?
-
CodeWizard over 8 yearsWhere do you see your email? on the same branch or is it on a different branch?
-
Kevin Cohen over 8 yearsSame 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 over 8 yearsI didn't understood what happened. can you provide screen shoot?
-
Jonah about 4 yearsand then
git push --force
? -
Chris Maes about 4 yearssince this rewrites your commits, yes. Consider using
git push --force-with-lease
to make sure not to crush work from your collegues. -
ravi over 3 yearsThis is exactly what I was looking for. Thank you :)
-
Matthew Strasiotto about 3 yearsA 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 findfunction_in_bashrc
. I mean, maybe there's no such thing as a bash script that doesn't include an ugly hack -
Matthew Strasiotto about 3 yearsIf anyone has better ideas for delaying evaluation of parameter substitution/shell expansion, please weigh in
-
Oscar Andersson over 2 yearsThanks 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. over 2 yearsWorks like a charm!
-
keypoint over 2 yearsworks for me! thanks!
-
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 thefilter-branch
(orfilter-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 agit commit --amend --author="John Doe ..."
here, and you can see that the committer is not John Doe.