Could I change my name and surname in all previous commits?

43,351

Solution 1

Use git-filter-branch.

git filter-branch --commit-filter 'if [ "$GIT_AUTHOR_NAME" = "Josh Lee" ];
  then export GIT_AUTHOR_NAME="Hobo Bob"; export [email protected];
  fi; git commit-tree "$@"'

This only affects the author, not the committer (which for most commits will be the same as the author). If you want to rewrite those as well, set the GIT_COMMITTER_NAME and GIT_COMMITTER_EMAIL variables.

The standard warning about rewriting history applies; only do it to history that has not yet been shared.

June 2018 Update

The manual now includes a solution, using --env-filter, in its examples: https://git-scm.com/docs/git-filter-branch#_examples :

git filter-branch --env-filter '
    if test "$GIT_AUTHOR_EMAIL" = "root@localhost"
    then
        [email protected]
    fi
    if test "$GIT_COMMITTER_EMAIL" = "root@localhost"
    then
        [email protected]
    fi
' -- --all

Solution 2

To rewrite both author and commiter in all selected commits:

git filter-branch --commit-filter \
'if [ "$GIT_AUTHOR_NAME" = "OldAuthor Name" ]; then \
export GIT_AUTHOR_NAME="Author Name";\
export [email protected];\
export GIT_COMMITTER_NAME="Commmiter Name";\
export [email protected];\
fi;\
git commit-tree "$@"'

Solution 3

If there are no other authors, you can do:

git filter-branch --commit-filter 'export GIT_AUTHOR_NAME="authorname"; \
export [email protected]; git commit-tree "$@"'

Solution 4

Save the script below as e.g. ~/.bin/git-replace-author and run it using, e.g:

git replace-author "John Ssmith" "John Smith" "[email protected]"

With no arguments, it updates all commits with your name to use your current email address according to Git config.

DEFAULT_NAME="$(git config user.name)"
DEFAULT_EMAIL="$(git config user.email)"
export OLD_NAME="${1:-$DEFAULT_NAME}"
export NEW_NAME="${2:-$DEFAULT_NAME}"
export NEW_EMAIL="${3:-$DEFAULT_EMAIL}"

echo "Old:" $OLD_NAME "<*>"
echo "New:" "$NEW_NAME <$NEW_EMAIL>"
echo "To undo, use: git reset $(git rev-parse HEAD)"

git filter-branch --env-filter \
'if [ "$GIT_AUTHOR_NAME" = "${OLD_NAME}" ]; then
    export GIT_AUTHOR_NAME="${NEW_NAME}"
    export GIT_AUTHOR_EMAIL="${NEW_EMAIL}"
    export GIT_COMMITTER_NAME="${NEW_NAME}"
    export GIT_COMMITTER_EMAIL="${NEW_EMAIL}"
fi'

Raw (to download)

Solution 5

Only if you haven't pushed your commits to the world. Other wise everyone else has your old name in their repo which is unlikely you can change everyone's.

Share:
43,351
Joshua
Author by

Joshua

Updated on October 06, 2020

Comments

  • Joshua
    Joshua over 3 years

    I would like to change my name, surname and email in my all commits, is it possible?

  • MaddTheSane
    MaddTheSane over 13 years
    If you’re using msysgit, you still have access to bash. Otherwise, I’ve no clue.
  • Tyler
    Tyler over 13 years
    @Joshua if you're using something where you don't have bash, you could probably use windows batch scripting, though I haven't tried it.
  • user11153
    user11153 almost 10 years
    It's not rewriting "Committer:" info.
  • chronospoon
    chronospoon over 9 years
    It's not intended to rewrite committer info. If you want to do that, export GIT_COMMITTER_NAME and GIT_COMMITTER_EMAIL as well (see accepted answer).
  • piotrek
    piotrek over 9 years
    and what about tags? this solution won't change author of tags
  • Will Sheppard
    Will Sheppard almost 9 years
    @Joshua check out the git repo on a linux box and perform the fix there
  • leo
    leo over 7 years
    True, but in some cases you have no choice. I my case I had a wrong email address configured in my git config (as I could see with "git config --global -l"). As a result, I had no commit activity showing up in my own Github repo (because the email address didn't match with the email configured in Github) ! To solve this, I fixed my local commits using the recipe from stackoverflow.com/a/23564785/2474068 (worked perfect) and then I pushed the changed commits to Github using "git push -u -f origin master" (with the force flag "-f"). That goes against accepted practice but I had no choice!
  • EnabrenTane
    EnabrenTane over 7 years
    Yes, my point was that any forks of that repo wouldn't have that change unless they accepted your force push. It would be challenging to get every fork to update :)
  • vikyd
    vikyd almost 7 years
    But how to apply changes to remote server?
  • user11153
    user11153 almost 7 years
    @Viky Try git push --all origin --force
  • vikyd
    vikyd almost 7 years
    It works for me ! I'm using GitLab, I have to Unprotect the branch before push command.
  • Michael Gecht
    Michael Gecht about 6 years
    As a short note: ~/.bin/ needs to be inside the users $PATH and the file needs to be executable, so run: chmod +x ~/.bin/git-replace-author.
  • Eugen Konkov
    Eugen Konkov about 6 years
    And what it do with arguments?
  • Eugen Konkov
    Eugen Konkov about 6 years
    Is there an options which result in new branch and leave source commits intact?
  • xiay
    xiay almost 6 years
    +1. Good solution. Would be even nicer if you put the old and new emails in two env var at the beginning of the line, something like: OLD_EMAIL=local@localhost && [email protected] && git filter-branch --env-filter " if test \"\$GIT_AUTHOR_EMAIL\" = \"$OLD_EMAIL\" then GIT_AUTHOR_EMAIL=$NEW_EMAIL fi if test \"\$GIT_COMMITTER_EMAIL\" = \"$OLD_EMAIL\" then GIT_COMMITTER_EMAIL=$NEW_EMAIL fi " -- --all then this answer would be workable from command-line
  • xiay
    xiay almost 6 years
    @EugenKonkov Source commits are intact because you create a branch/tree from the first commit you modify. If you want a branch to point to old commits, just first create a new branch before rewriting history.
  • Garret Wilson
    Garret Wilson over 5 years
    Wonderful, but don't forget --tag-name-filter cat to rewrite tags; see stackoverflow.com/a/7673115/421049 . Unfortunately the tagger emails don't seem to be updated; see stackoverflow.com/q/51790056/421049 .
  • David G
    David G almost 2 years
    @xiay Is root@localhost supposed to stay the same?