Changing author info in existing Git commits

If you are not setting the author info correctly or just want to use another email to prevent it from being exposed, you may want to change the author name and/or email of the existing commits. In the post, you will learn how to do that.

Take care to do that if you have pushed these commits to the remote server and there are other members who have access to that repository. Because the other members may have did some work based on your commits.

Change author info of the last commit

If you only want to change author info of the last commit, you can amend it to use new name and email.

# Change the last commit to use new author and email.

# Use --author option to specify the new author and email.
$ git commit --amend --no-edit --author "john <john@noreply.email.com>"

# Or
# Update the user info in configureation first, then amend the commit to
# use the new configured info.

$ git config user.name john
$ git config user.email john@noreply.email.0
# --reset-author, use the current user info.
$ git commit --amend --no-edit --reset-author

Note:

What git commit --amend does is replacing the tip of the current branch by creating a new commit., therefore it renew the commit date as well.

Change author info of multiple existing commits

To change the name and/or email of some specific existing commits, you can use rebase in an interactive mode which allows you to change the commit one by one. Then in the process you can use git commit --amend used above to do the change. See Git book: rewrite history for more details. Below is an example (for messy history, don’t use this method for inconsistent issue that may cause):

# Change the last two commits.
$ git rebase -i HEAD~2
# Action: change "pick" to "edit" in the prompted script for commits
# that you want to change
$ git commit --amend --no-edit --author "john "
$ git rebase --continue
$ git commit --amend --no-edit --author "john "
$ git rebase --continue

To change the name and/or email of the entire history, of course filter-branch can do that as GitHub: changing author info mentioned. In that guide it provides a script that use filter-branch command to rewrite the name and email if the commit email equals some value. However there are issues with filter-branch, there have been some alternatives to replace this command such as git-filter-repo.

If you run the script mentioned in GitHub: changing author info, the Git bash (v2.28.0) will give below warning:

$ ./change-author.sh
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.  See the
         filter-branch manual page for more details; to squelch this warning,
         set FILTER_BRANCH_SQUELCH_WARNING=1.
Proceeding with filter-branch...

Cannot rewrite branches: You have unstaged changes.

Here we use git-filter-repo command rather than filter-branch according the suggested way in above warning. Before you start, make your working directory clean.

First download git-filter-repo command (it requires Python3) and put the git-filter-repo file to a location on the PATH.

Then write a mailmap file in which you specify the name and/or email. Here we name it as my-mailmap and put below content that specifies to replace both the name and the email of a commit matching the specified commit email address:

john <john@noreply.email.com> <john@gmail.com>

Finally, run filter-repo with the mailmap you created:

$ git filter-repo --mailmap my-mailmap

About mailmap file

The --mailmap option needs a mailmap file of format accepted by git shortlog. Other forms of mailfile:

Replace name of a commit matching the specified commit email address:

Proper Name 

Replace only the email part of a commit matching the specified commit email address:

 

Replace both the name and the email of a commit matching the specified commit email address:

Proper Name  

Replace both the name and the email of a commit matching both the specified commit name and email address:

Proper Name  Commit Name 

Troubleshooting

# If your repository are not a fresh cloned one, use --force
$ git filter-repo --mailmap my-mailmap
Aborting: Refusing to destructively overwrite repo history since
this does not look like a fresh clone.
  (expected at most one entry in the reflog for HEAD)
Please operate on a fresh clone instead.  If you want to proceed
anyway, use --force.

# If it prompts below error, change "python3" to "python" in the git-filter-repo file
$ git filter-repo --mailmap my-mailmap
/usr/bin/env: ‘python3’: No such file or directory

Resources

git-filter-branch

  • Git book: rewriting history

  • GitHub: changing author info

    If you insist to use filter-branch command, run the script like below and wait a few seconds. Then the script will be executed if you don’t interrupt it with ctrl+c.

    $ ./change-author
    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.  See the
           filter-branch manual page for more details; to squelch this warning,
           set FILTER_BRANCH_SQUELCH_WARNING=1.
    Proceeding with filter-branch...
    
    Rewrite 6f5fae28ee6591861813c4a428379c752217dffe (1/1) (0 seconds passed, remaining 0 predicted)
    Ref 'refs/heads/master' was rewritten
    
    

git-filter-repo

  • git-filter-repo user manual

    Filtering of names & emails

    --mailmap

    ​ Use specified mailmap file (see git-shortlog(1) for details on the format) when rewriting author, committer, and tagger names and emails. If the specified file is part of git history, historical versions of the file will be ignored; only the current contents are consulted.

    --use-mailmap

    ​ Same as: –mailmap .mailmap

  • git-shortlog(1)

Changing the last commit in Git

Sometimes, you may want to change the last commit you’ve made. --amend allows you do that. With that option, you can replace the last commit with a new one. But take care to do that if you’ve pushed it to the remote and there are other members in the repository. In such case, they may have made changes based on your last commit, then remember to notice them to execute git pull --rebase to avoid troubles after you pushed the new commit .

A more complicated case is before you amend your commit, someone have pushed their commits based on your last commit. In such a case, a simple way is to execute git pull to get the new changes, and make a new commit in which changes of your last commit can be reverted with git revert command.

# Pull new changes that have been pushed after your last commit
$ git pull

# Revert your last commit. Note you may need to fix some conflicts if they occur.
# If nothing is wrong, a new commit will be generated automatically.
# There will be a chance to write the commit message, or you can leave it as it was.
# Examples: 
# git revert 6d84d27
# git revert HEAD~~
# git revert HEAD~3
$ git revert 

# Push
$ git push

A complicated method is to execute rebase command to make the subsequent commits being based on the changed new one. It is not discussed here.

Process of changing the last commit

Below is a full process to make sure every thing will be fine in various situations.

# Step 1
# Make sure you are at the tip of the branch (the others have not pushed new commits 
# based on your last one), notice the other members not to push during the process.

# Check whether you are ahead or behind the remote branch
$ git branch --vv

# If you are not behind the remote branch, go to the next step.
# If you are behind, see the second paragraph part of the article.

# Step 2
# Make modifications in the working directory

# Step 3
# Add the modifications
$ git add functions.php

# Step 4
# Recommit with --amend option
# --amend, replace the tip of the current barnch by creating a new commit
$ git commit --amend -m 'new commit message'

# Step 5
# If you have not pushed the last commit.
$ git push
# If the last commit has been pushed to remote, repush it with --force.
# --force, force to push to allow overwriting the commits in the remote.
# Use --force with care.
$ git push --force

# Step 6
# Notice others to run "git pull --reabase" if there are other members.

If you want to change the commit for specific needs, such as only changing the commit message or keeping the old commit message, see below.

1. Change the last commit without changing commit message

# Amend commit without changing commit message
# --no-edit, use the old commit message without lauching an editor to change it
$ git commit --amend --no-edit

2. Change only the commit message in the last commit

# Change the commit message
$ git commit --amend -m 'new commit message'

3. Change only the author info in the last commit

Below is an example to change the author to be “john” and the email to be “john@example.com”. Remember to wrap the email with “ in the first command.

# Change author info in the last commit.
# the new author is john, and email is john@example.com
# --author="<Author <Author email>"
$ git commit --amend --no-edit --author="john <john@example.com>"

# Or
# First set the author and email for the repo
# and then change the commit with the new configured author and email.
# --reset-author, renew the author infor in the commit with the configured user info.
$ git config user.name john
$ git config user.email john@example.com
$ git commit --amend --no-edit --reset-author

Resources

git commit

Committing only a commit message in Git

Commit only a commit message in Git. Last updated: 2018-12-16

Usually, a commit can not be empty, but you can use --allow-empty option to do this:

# Commit only a commit message.
$ git commit --allow-empty -m 'my commit message'

Undoing a commit in Git

Here you will learn how to undo a commit (no matter it has been pushed or not have been pushed yet) in a safe and simple way. Changing the last commit gives more choices if you want to change the remote commit history and what you should do in various situations.

Undo a commit that hasn’t been pushed yet

If you made some mistakes in a commit, you can redo it in a new commit using --amend option. Just fix your mistakes, stage (add) them and make a new commit as below:

# Redo the last commit.
# --amend, replace the last commit with a new one.
$ git commit --amend

If above solution does not suit you, reset can be used to just undo the commit (be careful to use reset):

# Discard the last commit. The commit's modifications in working tree are kept.
$ git reset HEAD~

# Discard the last commit. The commit's modifications in staging area are kept.
$ git reset --soft HEAD~

# Discard the last commit. The commit's modifications in working tree are not kept.
$ git reset --hard HEAD~

Undo a commit that has been pushed

If a commit has been pushed to the remote repository, changing the history in the remote repository is not a good idea. You can let Git to make a new commit which reverses the modifications in the last commit.

git revert command works for you :

# Reverse a commit.
$ git revert -m 1 HEAD

Afterwards, push it to the remote repository again.