How to change the author and committer name and e-mail of multiple commits in Git?

后端 未结 30 3039
野性不改
野性不改 2020-11-21 04:50

I was writing a simple script in the school computer, and committing the changes to Git (in a repo that was in my pendrive, cloned from my computer at home). After several c

相关标签:
30条回答
  • 2020-11-21 05:14

    NOTE: This answer changes SHA1s, so take care when using it on a branch that has already been pushed. If you only want to fix the spelling of a name or update an old email, git lets you do this without rewriting history using .mailmap. See my other answer.

    Using Interactive Rebase

    You could do

    git rebase -i -p <some HEAD before all of your bad commits>
    

    Then mark all of your bad commits as "edit" in the rebase file. If you also want to change your first commit, you have to manually add it as the first line in the rebase file (follow the format of the other lines). Then, when git asks you to amend each commit, do

     git commit --amend --author "New Author Name <email@address.com>" 
    

    edit or just close the editor that opens, and then do

    git rebase --continue
    

    to continue the rebase.

    You could skip opening the editor altogether here by appending --no-edit so that the command will be:

    git commit --amend --author "New Author Name <email@address.com>" --no-edit && \
    git rebase --continue
    

    Single Commit

    As some of the commenters have noted, if you just want to change the most recent commit, the rebase command is not necessary. Just do

     git commit --amend --author "New Author Name <email@address.com>"
    

    This will change the author to the name specified, but the committer will be set to your configured user in git config user.name and git config user.email. If you want to set the committer to something you specify, this will set both the author and the committer:

     git -c user.name="New Author Name" -c user.email=email@address.com commit --amend --reset-author
    

    Note on Merge Commits

    There was a slight flaw in my original response. If there are any merge commits between the current HEAD and your <some HEAD before all your bad commits>, then git rebase will flatten them (and by the way, if you use GitHub pull requests, there are going to be a ton of merge commits in your history). This can very often lead to a very different history (as duplicate changes may be "rebased out"), and in the worst case, it can lead to git rebase asking you to resolve difficult merge conflicts (which were likely already resolved in the merge commits). The solution is to use the -p flag to git rebase, which will preserve the merge structure of your history. The manpage for git rebase warns that using -p and -i can lead to issues, but in the BUGS section it says "Editing commits and rewording their commit messages should work fine."

    I've added -p to the above command. For the case where you're just changing the most recent commit, this is not an issue.

    Update for modern git clients (July 2020)

    Use --rebase-merges instead of -p (-p is deprecated and has serious issues).

    0 讨论(0)
  • 2020-11-21 05:14

    I adapted this solution which works by ingesting a simple author-conv-file (format is the same as one for git-cvsimport). It works by changing all users as defined in the author-conv-file across all branches.

    We used this in conjunction with cvs2git to migrate our repository from cvs to git.

    i.e. Sample author-conv-file

    john=John Doe <john.doe@hotmail.com>
    jill=Jill Doe <jill.doe@hotmail.com>
    

    The script:

     #!/bin/bash
    
     export $authors_file=author-conv-file
    
     git filter-branch -f --env-filter '
    
     get_name () {
         grep "^$1=" "$authors_file" |
         sed "s/^.*=\(.*\) <.*>$/\1/"
     }
    
     get_email () {
         grep "^$1=" "$authors_file" |
         sed "s/^.*=.* <\(.*\)>$/\1/"
     }
    
     GIT_AUTHOR_NAME=$(get_name $GIT_COMMITTER_NAME) &&
         GIT_AUTHOR_EMAIL=$(get_email $GIT_COMMITTER_NAME) &&
         GIT_COMMITTER_NAME=$GIT_AUTHOR_NAME &&
         GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL &&
         export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL &&
         export GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL
     ' -- --all
    
    0 讨论(0)
  • 2020-11-21 05:14

    Your problem is really common. See "Using Mailmap to Fix Authors List in Git"

    For the sake of simplicity, I have created a script to ease the process: git-changemail

    After putting that script on your path, you can issue commands like:

    • Change author matchings on current branch

      $ git changemail -a old@email.com -n newname -m new@email.com
      
    • Change author and committer matchings on <branch> and <branch2>. Pass -f to filter-branch to allow rewriting backups

      $ git changemail -b old@email.com -n newname -m new@email.com -- -f &lt;branch> &lt;branch2>
      
    • Show existing users on repo

      $ git changemail --show-both
      

    By the way, after making your changes, clean the backup from the filter-branch with: git-backup-clean

    0 讨论(0)
  • 2020-11-21 05:15

    This answer uses git-filter-branch, for which the docs now give this warning:

    git filter-branch has a plethora of pitfalls that can produce non-obvious manglings of the intended history rewrite (and can leave you with little time to investigate such problems since it has such abysmal performance). These safety and performance issues cannot be backward compatibly fixed and as such, its use is not recommended. Please use an alternative history filtering tool such as git filter-repo. If you still need to use git filter-branch, please carefully read SAFETY (and PERFORMANCE) to learn about the land mines of filter-branch, and then vigilantly avoid as many of the hazards listed there as reasonably possible.

    Changing the author (or committer) would require re-writing all of the history. If you're okay with that and think it's worth it then you should check out git filter-branch. The man page includes several examples to get you started. Also note that you can use environment variables to change the name of the author, committer, dates, etc. -- see the "Environment Variables" section of the git man page.

    Specifically, you can fix all the wrong author names and emails for all branches and tags with this command (source: GitHub help):

    #!/bin/sh
    
    git filter-branch --env-filter '
    OLD_EMAIL="your-old-email@example.com"
    CORRECT_NAME="Your Correct Name"
    CORRECT_EMAIL="your-correct-email@example.com"
    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
    
    0 讨论(0)
  • 2020-11-21 05:16

    If you are using Eclipse with EGit, then there is a quite easy solution.
    Assumption: you have commits in a local branch 'local_master_user_x' which cannot be pushed to a remote branch 'master' because of the invalid user.

    1. Checkout the remote branch 'master'
    2. Select the projects/folders/files for which 'local_master_user_x' contains changes
    3. Right-click - Replace with - Branch - 'local_master_user_x'
    4. Commit these changes again, this time as the correct user and into the local branch 'master'
    5. Push to remote 'master'
    0 讨论(0)
  • 2020-11-21 05:17
    1. Change commit author name & email by Amend, then replacing old-commit with new-one:

      $ git checkout <commit-hash>                            # checkout to the commit need to modify  
      $ git commit --amend --author "name <author@email.com>" # change the author name and email
      
      $ git replace <old-commit-hash> <new-commit-hash>      # replace the old commit by new one
      $ git filter-branch -- --all                           # rewrite all futures commits based on the replacement                   
      
      $ git replace -d <old-commit-hash>     # remove the replacement for cleanliness 
      $ git push -f origin HEAD              # force push 
      
    2. Another way Rebasing:

      $ git rebase -i <good-commit-hash>      # back to last good commit
      
      # Editor would open, replace 'pick' with 'edit' before the commit want to change author
      
      $ git commit --amend --author="author name <author@email.com>"  # change the author name & email
      
      # Save changes and exit the editor
      
      $ git rebase --continue                # finish the rebase
      
    0 讨论(0)
提交回复
热议问题