78

When I started using git I just did a git init and started calling add and commit. Now I am starting to pay attention and I can see that my commits are showing up as cowens@localmachine, rather than the address I want. It appears as if setting GIT_AUTHOR_EMAIL and GIT_COMMITTER_EMAIL will do what I want, but I still have those old commits with the wrong email address/name. How can I correct the old commits?

2

4 Answers 4

85

You can go back and fix all your commits with a single call to git filter-branch. This has the same effect as rebase, but you only need to do one command to fix all your history, instead of fixing each commit individually.

You can fix all the wrong emails with this command:

git filter-branch --env-filter '
    oldname="(old name)"
    oldemail="(old email)"
    newname="(new name)"
    newemail="(new email)"
    [ "$GIT_AUTHOR_EMAIL"="$oldemail" ] && GIT_AUTHOR_EMAIL="$newemail"
    [ "$GIT_COMMITTER_EMAIL"="$oldemail" ] && GIT_COMMITTER_EMAIL="$newemail"
    [ "$GIT_AUTHOR_NAME"="$oldname" ] && GIT_AUTHOR_NAME="$newname"
    [ "$GIT_COMMITTER_NAME"="$oldname" ] && GIT_COMMITTER_NAME="$newname"
    ' HEAD

More information is available from the git docs

12
  • 13
    well, git filter-branch --env-filter 'export GIT_AUTHOR_EMAIL="[email protected]";GIT_AUTHOR_NAME="Foo"' is a lot simpler, thanks. This would be the accepted answer if I could change it (it looks like there is a bug with Server Fault). May 27, 2009 at 18:07
  • 7
    Note that the export lines should NOT have spaces on either side of the equals sign. I.e. they should look like this: export GIT_AUTHOR_EMAIL="(correct email)" ; Nov 3, 2009 at 12:12
  • 1
    Now, how would I do this on Windows?
    – Deckard
    Mar 9, 2012 at 21:56
  • 2
    @Deckard: save the script to a text file such as fixcommits.sh, then run Git Bash and run the script. I put the script file in the root of my repo, then navigated to that folder in Git Bash, then I ran the script with ./fixcommits.sh
    – Avalanchis
    Apr 30, 2012 at 0:20
  • 2
    Addendum 1 This command format was not working for me, but if/then did: if [ "$GIT_AUTHOR_EMAIL" = "$oldemail" ]; then GIT_AUTHOR_EMAIL="$newemail"; fi
    – Josh M.
    Apr 14, 2015 at 17:02
28

Git's filter-branch command is powerful, but it's horribly unwieldy to use for anything non-trivial, like for example, if you have more than one author to correct.

Here's an alternative I found useful, which uses the .mailmap feature described in the git-shortlog manpage. This provides an author mapping mechanism we can use with git log's formatting facility. We can use it to generate the commands to pick and amend amend a named sequence of commits.

For example, suppose you want to correct the authorship on a branch $BRANCH, starting at a commit $START.

You need to create a .mailmap file in the top directory of your repository which maps the existing author names to he correct ones. You can get a list of the existing author names with:

git shortlog -se

You need to end up with a .mailmap file like this (say):

You <[email protected]>   cowens@localmachine
You <[email protected]>   root@localmachine

Now you can use git log's formatting feature to generate the commands to rewrite $BRANCH as $BRANCH2.

git checkout -b $BRANCH2 $START
git log --reverse --pretty=format:"cherry-pick %H; commit --amend --author='%aN <%aE>' -C %H" $START..$BRANCH | sh - 

The first command creates a new empty branch sprouting from the commit $START. For each commit between $START and then end of $BRANCH, the second command cherry picks the original commit on to the end of the current branch $BRANCH2, and amends it to set the author correctly.

This is also generally applicable - put this in your ~/.gitconfig:

[alias]
    # git reauthor $START..$END
    reauthor = !sh -c 'eval `git log --reverse --topo-order --pretty=format:\"git cherry-pick %H &&  git commit --amend -C %H --author=\\\"%aN <%aE>\\\" && \" $0 ` "echo success" '

So when you need to correct authors, now you just then need to generate a .mapfile and do:

git checkout -b $BRANCH2 $START
git reauthor $START..$BRANCH

The original branch ref can be reassigned to the new one, and the new one deleted:

git checkout $BRANCH
git reset --hard $BRANCH2 # be careful with this command
git branch -d $BRANCH2
1
  • This is awesome. I'd bounty you if I had more rep. Thanks :)
    – pistache
    Dec 10, 2012 at 8:32
9

Combining the answer from How do I fix the metainformation on the first commit in git?

### Fix the first commit ###    
# create a temporary tag for the root-most commit so we can reference it
git tag root `git rev-list HEAD | tail -1`
# check it out on its own temporary branch
git checkout -b new-root root
# amend the commit
git commit --amend --author "Foo [email protected]"
# (or if you've set the proper git **config** values)
git commit --amend -C HEAD --reset-author
# now you've changed the commit message, so checkout the original branch again
git checkout @{-1}
# and rebase it onto your new root commit
git rebase --onto new-root root
### Fix the rest of the commits ###
git rebase -i root
# edit the file to read "edit <commit number> for each entry
# amend the commit
git commit --amend --author "Foo [email protected]"
# (or if you've set the proper git **config** values)
git commit --amend -C HEAD --reset-author
# move to the next commit
git rebase --continue    
# continue running the last two commands until you see
# Successfully rebased and updated refs/heads/master.
### Clean up ###
# nuke the temporary branch we created
git branch -d new-root
# nuke the temporary tag we created
git tag -d root
1
5

To follow jedberg's answer: You can use rebase -i and choose to edit the commits in question. If you use git commit --amend --author <AUTHOR DETAILS> and then git rebase continue you can go through and fix the history.

Not the answer you're looking for? Browse other questions tagged .