How to amend several commits in Git to change author

117k views Asked by At

I have made a series of commits in Git and I realise now that I forgot to set my user name and user email properties correctly (new machine). I have not yet pushed these commits to my repository, so how can I correct these commits before I do so (only the 3 latest commits on the master branch)?

I have been looking at git reset and git commit -C <id> --reset-author, but I don't think I'm on the right track.

8

There are 8 answers

15
Cascabel On BEST ANSWER

Warning: now deprecated in favor of filter-repo.

Rebase/amend seems inefficient, when you have the power of filter-branch at your fingertips:

git filter-branch --env-filter 'if [ "$GIT_AUTHOR_EMAIL" = "incorrect@email" ]; then
     GIT_AUTHOR_EMAIL=correct@email;
     GIT_AUTHOR_NAME="Correct Name";
     GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL;
     GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME"; fi' -- --all

(split across lines for clarity, but not necessary)

Be sure to inspect the result when you're done, to make sure that you didn't change anything you didn't mean to!

0
Fernando Diaz Garrido On

I believe what you are looking for is git rebase --interactive

It allows you to go reset to an specific commit and then go throw the history changing adding or grouping commits

Here you have an explanation https://web.archive.org/web/20100213104931/http://blog.madism.org/index.php/2007/09/09/138-git-awsome-ness-git-rebase-interactive

0
Kaka Ruto On

If you're looking for a script, this one came handy for me.

  1. Download the script from GitHub and save it to an easily-accessible location.

  2. Change the permissions of the script file to allow it to execute:

    chmod +x changeauthor.sh

  3. Navigate into the repository with the incorrect commit history

    cd path/to/repo

  4. Run the script (with or without flags)

    ../path/to/changeauthor.sh --old-email [email protected] \
        --new-email [email protected] --new-name "Kaka Ruto" --remote origin
    

Be careful as this will rewrite all history in your current dir repository! Good thing is the script give you warnings and info about what you're about to do

Read more here https://www.adamdehaven.com/blog/update-commit-history-author-information-for-git-repository/

0
mr. Y On

As suggested in this answer git-filter-repo is preferred for the task.

However to simply change author name and/or email one can use --mailmap or --use-mailmap instead of callbacks.

You need to create a mailmap file according to the format (see git-filter-repo/docs or git-scm.com/docs)

Then simply run

git filter-repo --mailmap .mailmap
6
Chris Maes On

To change the author only for the last commit:

git commit --amend --author 'Author Name <[email protected]>' --no-edit

Suppose you only want to change the author for the last N commits:

git rebase -i HEAD~4 -x "git commit --amend --author 'Author Name <[email protected]>' --no-edit"

Change the committer as well:

as noted by @sshine and @Hermann.Gruber, the previous commands change the author only. To change the committer as well, you can use the solution proposed by @Hermann.Gruber:

git rebase -i HEAD~4 -x "GIT_COMMITTER_NAME='Author Name' GIT_COMMITTER_EMAIL='[email protected]' git commit --amend --author 'Author Name <[email protected]>' --no-edit"

NOTES

  • the --no-edit flag makes sure the git commit --amend doesn't ask an extra confirmation
  • when you use git rebase -i, you can manually select the commits where to change the author,

the file you edit will look like this:

pick 897fe9e simplify code a little
pick abb60f9 add new feature
exec git commit --amend --author 'Author Name <[email protected]>' --no-edit
pick dc18f70 bugfix
15
Alex On

The interactive rebase approach is pretty nice when used in conjunction with exec. You can run any shell command against a specific commit or all commits in the rebase.

First set your git author settings

git config --global user.name "John Doe"
git config --global user.email [email protected]

Then to reset the author for all commits after the given BASE_SHA:

git rebase -i BASE_SHA -x \
  "git commit --amend --author 'John Doe <[email protected]>' -CHEAD"

This will pop up your editor to confirm the changes. All you need to do here is save and quit and it will go through each commit and run the command specified in the -x flag.

3
stevec On

This method was documented by GitHub for this very purpose (though GitHub has since removed it). The steps are:

  1. Open the terminal and make a bare clone of your repo
git clone --bare https://github.com/user/repo.git
cd repo
  1. Edit the following script (replacing OLD_EMAIL, CORRECT_EMAIL, and CORRECT_NAME)
#!/bin/sh

git filter-branch --env-filter '
OLD_EMAIL="[email protected]"
CORRECT_NAME="Your Correct Name"
CORRECT_EMAIL="[email protected]"
if [ "$GIT_COMMITTER_EMAIL" = "$OLD_EMAIL" ]
then
    export GIT_COMMITTER_NAME="$CORRECT_NAME"
    export GIT_COMMITTER_EMAIL="$CORRECT_EMAIL"
fi
if [ "$GIT_AUTHOR_EMAIL" = "$OLD_EMAIL" ]
then
    export GIT_AUTHOR_NAME="$CORRECT_NAME"
    export GIT_AUTHOR_EMAIL="$CORRECT_EMAIL"
fi
' --tag-name-filter cat -- --branches --tags
  1. Copy/paste the script into your terminal and press enter to run it.
  2. Push your changes with git push --force --tags origin 'refs/heads/*' and you're done!
3
charsi On

The highest voted answer here is now out of date. Git shows this scary warning when using git filter-branch -

WARNING: git-filter-branch has a glut of gotchas generating mangled history
         rewrites. Hit Ctrl-C before proceeding to abort, then use an
         alternative filtering tool such as 'git filter-repo'
         (https://github.com/newren/git-filter-repo/) instead.

filter-repo is not (yet) part of git and needs to be installed separately.

# Requires git v2.22+ and python v3.5+. Check with -
git --version && python3 --version
    
# Install using pip
pip3 install git-filter-repo    
    

To replace only the email in previous commits run the the command like this -

git filter-repo --email-callback '
    return email if email != b"incorrect@email" else b"correct@email"
' 

To replace both, email and author name in the previous commits run the the command like this -

git filter-repo --commit-callback '
    if commit.author_email == b"incorrect@email":
        commit.author_email = b"correct@email" 
        commit.author_name = b"Correct Name"
        commit.committer_email = b"correct@email" 
        commit.committer_name = b"Correct Name"
' 

Make sure the indents are there when you paste the command in your terminal. The callback uses python syntax so indents are important.

Read more about filter-repo callbacks in the docs.