Advertisement
Advertisement


How to change the commit author for one specific commit?


Question

I want to change the author of one specific commit in the history. It's not the last commit.

I know about this question - How do I change the author of a commit in git?

But I am thinking about something, where I identify the commit by hash or short-hash.

2018/06/24
1
2190
6/24/2018 7:59:23 AM

Accepted Answer

Interactive rebase off of a point earlier in the history than the commit you need to modify (git rebase -i <earliercommit>). In the list of commits being rebased, change the text from pick to edit next to the hash of the one you want to modify. Then when git prompts you to change the commit, use this:

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

For example, if your commit history is A-B-C-D-E-F with F as HEAD, and you want to change the author of C and D, then you would...

  1. Specify git rebase -i B (here is an example of what you will see after executing the git rebase -i B command)
    • if you need to edit A, use git rebase -i --root
  2. Change the lines for both C and D from pick to edit
  3. Exit the editor (for vim, this would be pressing Esc and then typing :wq).
  4. Once the rebase started, it would first pause at C
  5. You would git commit --amend --author="Author Name <[email protected]>"
  6. Then git rebase --continue
  7. It would pause again at D
  8. Then you would git commit --amend --author="Author Name <[email protected]>" again
  9. git rebase --continue
  10. The rebase would complete.
  11. Use git push -f to update your origin with the updated commits.
2020/04/03
3711
4/3/2020 10:25:31 AM

The accepted answer to this question is a wonderfully clever use of interactive rebase, but it unfortunately exhibits conflicts if the commit we are trying to change the author of used to be on a branch which was subsequently merged in. More generally, it does not work when handling messy histories.

Since I am apprehensive about running scripts which depend on setting and unsetting environment variables to rewrite git history, I am writing a new answer based on this post which is similar to this answer but is more complete.

The following is tested and working, unlike the linked answer. Assume for clarity of exposition that 03f482d6 is the commit whose author we are trying to replace, and 42627abe is the commit with the new author.

  1. Checkout the commit we are trying to modify.

    git checkout 03f482d6
    
  2. Make the author change.

    git commit --amend --author "New Author Name <New Author Email>"
    

    Now we have a new commit with hash assumed to be 42627abe.

  3. Checkout the original branch.

  4. Replace the old commit with the new one locally.

    git replace 03f482d6 42627abe
    
  5. Rewrite all future commits based on the replacement.

    git filter-branch -- --all
    
  6. Remove the replacement for cleanliness.

    git replace -d 03f482d6
    
  7. Push the new history (only use --force if the below fails, and only after sanity checking with git log and/or git diff).

    git push --force-with-lease
    

Instead of 4-6 you can just rebase onto new commit:

git rebase -i 42627abe
2018/07/09

Github documentation contains a script that replaces the committer info for all commits in a branch.

  • Run the following script from terminal after changing the variable values

    #!/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
    
  • Push the corrected history to GitHub:

    git push --force --tags origin 'refs/heads/*'
    

    OR if you like to push selected references of the branches then use

    git push --force --tags origin 'refs/heads/develop'
    
2020/01/12

  • Reset your email to the config globally:

    git config --global user.email [email protected]

  • Now reset the author of your commit without edit required:

    git commit --amend --reset-author --no-edit

2018/02/22

You can change author of last commit using the command below.

git commit --amend --author="Author Name <[email protected]>"

However, if you want to change more than one commits author name, it's a bit tricky. You need to start an interactive rebase then mark commits as edit then amend them one by one and finish.

Start rebasing with git rebase -i. It will show you something like this.

https://monosnap.com/file/G7sdn66k7JWpT91uiOUAQWMhPrMQVT.png

Change the pick keyword to edit for the commits you want to change the author name.

https://monosnap.com/file/dsq0AfopQMVskBNknz6GZZwlWGVwWU.png

Then close the editor. For the beginners, hit Escape then type :wq and hit Enter.

Then you will see your terminal like nothing happened. Actually you are in the middle of an interactive rebase. Now it's time to amend your commit's author name using the command above. It will open the editor again. Quit and continue rebase with git rebase --continue. Repeat the same for the commit count you want to edit. You can make sure that interactive rebase finished when you get the No rebase in progress? message.

2020/02/16

The answers in the question to which you linked are good answers and cover your situation (the other question is more general since it involves rewriting multiple commits).

As an excuse to try out git filter-branch, I wrote a script to rewrite the Author Name and/or Author Email for a given commit:

#!/bin/sh

#
# Change the author name and/or email of a single commit.
#
# change-author [-f] commit-to-change [branch-to-rewrite [new-name [new-email]]]
#
#     If -f is supplied it is passed to "git filter-branch".
#
#     If <branch-to-rewrite> is not provided or is empty HEAD will be used.
#     Use "--all" or a space separated list (e.g. "master next") to rewrite
#     multiple branches.
#
#     If <new-name> (or <new-email>) is not provided or is empty, the normal
#     user.name (user.email) Git configuration value will be used.
#

force=''
if test "x$1" = "x-f"; then
    force='-f'
    shift
fi

die() {
    printf '%s\n' "[email protected]"
    exit 128
}
targ="$(git rev-parse --verify "$1" 2>/dev/null)" || die "$1 is not a commit"
br="${2:-HEAD}"

TARG_COMMIT="$targ"
TARG_NAME="${3-}"
TARG_EMAIL="${4-}"
export TARG_COMMIT TARG_NAME TARG_EMAIL

filt='

    if test "$GIT_COMMIT" = "$TARG_COMMIT"; then
        if test -n "$TARG_EMAIL"; then
            GIT_AUTHOR_EMAIL="$TARG_EMAIL"
            export GIT_AUTHOR_EMAIL
        else
            unset GIT_AUTHOR_EMAIL
        fi
        if test -n "$TARG_NAME"; then
            GIT_AUTHOR_NAME="$TARG_NAME"
            export GIT_AUTHOR_NAME
        else
            unset GIT_AUTHOR_NAME
        fi
    fi

'

git filter-branch $force --env-filter "$filt" -- $br
2014/05/18

Source: https://stackoverflow.com/questions/3042437
Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Email: [email protected]