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

后端 未结 30 3035
野性不改
野性不改 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 04:52

    For a single commit:

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

    (extracted from asmeurer's answer)

    0 讨论(0)
  • 2020-11-21 04:52

    We have experienced an issue today where a UTF8 character in an author name was causing trouble on the build server, so we had to rewrite the history to correct this. The steps taken were:

    Step 1: Change your username in git for all future commits, as per instructions here: https://help.github.com/articles/setting-your-username-in-git/

    Step 2: Run the following bash script:

    #!/bin/sh
    
    REPO_URL=ssh://path/to/your.git
    REPO_DIR=rewrite.tmp
    
    # Clone the repository
    git clone ${REPO_URL} ${REPO_DIR}
    
    # Change to the cloned repository
    cd ${REPO_DIR}
    
    # Checkout all the remote branches as local tracking branches
    git branch --list -r origin/* | cut -c10- | xargs -n1 git checkout
    
    # Rewrite the history, use a system that will preseve the eol (or lack of in commit messages) - preferably Linux not OSX
    git filter-branch --env-filter '
    OLD_EMAIL="me@something.com"
    CORRECT_NAME="New Me"
    
    if [ "$GIT_COMMITTER_EMAIL" = "$OLD_EMAIL" ]
    then
        export GIT_COMMITTER_NAME="$CORRECT_NAME"
    fi
    if [ "$GIT_AUTHOR_EMAIL" = "$OLD_EMAIL" ]
    then
        export GIT_AUTHOR_NAME="$CORRECT_NAME"
    fi
    ' --tag-name-filter cat -- --branches --tags
    
    # Force push the rewritten branches + tags to the remote
    git push -f
    
    # Remove all knowledge that we did something
    rm -rf ${REPO_DIR}
    
    # Tell your colleagues to `git pull --rebase` on all their local remote tracking branches
    

    Quick overview: Checkout your repository to a temp file, checkout all the remote branches, run the script which will rewrite the history, do a force push of the new state, and tell all your colleagues to do a rebase pull to get the changes.

    We had trouble with running this on OS X because it somehow messed up line endings in commit messages, so we had to re-run it on a Linux machine afterwards.

    0 讨论(0)
  • 2020-11-21 04:53

    Try this out. It will do the same as above mentioned, but interactively.

    bash <(curl -s  https://raw.githubusercontent.com/majdarbash/git-author-change-script/master/run.sh)
    

    Reference: https://github.com/majdarbash/git-author-change-script

    0 讨论(0)
  • 2020-11-21 04:54

    In the case where just the top few commits have bad authors, you can do this all inside git rebase -i using the exec command and the --amend commit, as follows:

    git rebase -i HEAD~6 # as required
    

    which presents you with the editable list of commits:

    pick abcd Someone else's commit
    pick defg my bad commit 1
    pick 1234 my bad commit 2
    

    Then add exec ... --author="..." lines after all lines with bad authors:

    pick abcd Someone else's commit
    pick defg my bad commit 1
    exec git commit --amend --author="New Author Name <email@address.com>" -C HEAD
    pick 1234 my bad commit 2
    exec git commit --amend --author="New Author Name <email@address.com>" -C HEAD
    

    save and exit editor (to run).

    This solution may be longer to type than some others, but it's highly controllable - I know exactly what commits it hits.

    Thanks to @asmeurer for the inspiration.

    0 讨论(0)
  • 2020-11-21 04:55

    If you are the only user of this repository, you can rewrite history using either git filter-branch (as svick wrote), or git fast-export/git fast-import plus filter script (as described in article referenced in docgnome answer), or interactive rebase. But either of those would change revisions from first changed commit onwards; this means trouble for anybody that based his/her changes on your branch pre-rewrite.

    RECOVERY

    If other developers didn't based their work on pre-rewrite version, simplest solution would be to re-clone (clone again).

    Alternatively they can try git rebase --pull, which would fast-forward if there weren't any changes in their repository, or rebase their branch on top of re-written commits (we want to avoid merge, as it would keep pre-rewrite comits forever). All of this assuming that they do not have not comitted work; use git stash to stash away changes otherwise.

    If other developers use feature branches, and/or git pull --rebase doesn't work e.g. because upstream is not set up, they have to rebase their work on top of post-rewrite commits. For example just after fetching new changes (git fetch), for a master branch based on / forked from origin/master, one needs to run

    $ git rebase --onto origin/master origin/master@{1} master
    

    Here origin/master@{1} is pre-rewrite state (before fetch), see gitrevisions.


    Alternate solution would be to use refs/replace/ mechanism, available in Git since version 1.6.5. In this solution you provide replacements for commits that have wrong email; then anybody who fetches 'replace' refs (something like fetch = +refs/replace/*:refs/replace/* refspec in appropriate place in their .git/config) would get replacements transparently, and those who do not fetch those refs would see old commits.

    The procedure goes something like this:

    1. Find all commits with wrong email, for example using

      $ git log --author=user@wrong.email --all
      
    2. For each wrong commit, create a replacement commit, and add it to object database

      $ git cat-file -p <ID of wrong commit> | 
        sed -e 's/user@wrong\.email/user@example.com/g' > tmp.txt
      $ git hash-object -t commit -w tmp.txt
      <ID of corrected commit>
      
    3. Now that you have corrected commit in object database, you have to tell git to automatically and transparently replace wrong commit by corrected one using git replace command:

      $ git replace <ID of wrong commit> <ID of corrected commit>
      
    4. Finally, list all replacement to check if this procedure succeded

      $ git replace -l
      

      and check if replacements take place

      $ git log --author=user@wrong.email --all
      

    You can of course automate this procedure... well, all except using git replace which doesn't have (yet) batch mode, so you would have to use shell loop for that, or replace "by hand".

    NOT TESTED! YMMV.

    Note that you might encounter some rough corners when using refs/replace/ mechanism: it is new, and not yet very well tested.

    0 讨论(0)
  • 2020-11-21 04:58

    I use the following to rewrite the author for an entire repository, including tags and all branches:

    git filter-branch --tag-name-filter cat --env-filter "
      export GIT_AUTHOR_NAME='New name';
      export GIT_AUTHOR_EMAIL='New email'
    " -- --all
    

    Then, as described in the MAN page of filter-branch, remove all original refs backed up by filter-branch (this is destructive, backup first):

    git for-each-ref --format="%(refname)" refs/original/ | \
    xargs -n 1 git update-ref -d
    
    0 讨论(0)
提交回复
热议问题