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

后端 未结 30 3057
野性不改
野性不改 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: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  | 
        sed -e 's/user@wrong\.email/user@example.com/g' > tmp.txt
      $ git hash-object -t commit -w tmp.txt
      
      
    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  
      
    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.

提交回复
热议问题