2703

我正在学校计算机上编写一个简单的脚本,并将更改提交到 Git(在我的笔式驱动器中的一个存储库中,从我家的计算机克隆)。在几次提交之后,我意识到我是以 root 用户的身份提交的东西。

有没有办法将这些提交的作者更改为我的名字?

4

40 回答 40

1741

注意:此答案会更改 SHA1,因此在已推送的分支上使用它时要小心。如果您只想修复名称的拼写或更新旧电子邮件,git 允许您执行此操作而无需使用.mailmap. 请参阅我的其他答案

使用交互式变基

你可以做

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

然后在 rebase 文件中将所有错误提交标记为“编辑”。如果您还想更改第一次提交,则必须手动将其添加为 rebase 文件的第一行(遵循其他行的格式)。然后,当 git 要求您修改每个提交时,执行

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

编辑或关闭打开的编辑器,然后执行

git rebase --continue

继续变基。

您可以通过追加跳过在此处完全打开编辑器,--no-edit 以便命令为:

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

单次提交

正如一些评论者所指出的,如果您只想更改最近的提交,则不需要 rebase 命令。做就是了

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

这会将作者更改为指定的名称,但提交者将设置为您在git config user.name和中配置的用户git config user.email。如果您想将提交者设置为您指定的内容,这将同时设置作者和提交者:

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

合并提交注意事项

我原来的回答有一点小瑕疵。HEAD如果在 current和 your之间有任何合并提交<some HEAD before all your bad commits>,那么git rebase会将它们展平(顺便说一下,如果您使用 GitHub 拉取请求,那么您的历史记录中将会有大量的合并提交)。这通常会导致非常不同的历史记录(因为重复的更改可能会“重新设置为基础”),并且在最坏的情况下,它可能会导致git rebase要求您解决困难的合并冲突(可能已经在合并提交中解决了) . 解决方案是使用-p标志 to git rebase,这将保留您的历史合并结构。手册页git rebase警告说使用-pand-i可能会导致问题,但在BUGS它说“编辑提交和改写他们的提交消息应该可以正常工作”部分。

我已经添加-p到上面的命令中。对于您只是更改最近提交的情况,这不是问题。

现代 git 客户端更新(2020 年 7 月)

使用--rebase-merges代替-p(-p已弃用并且存在严重问题)。

于 2009-08-24T03:08:51.323 回答
1453

这个答案使用git-filter-branch文档现在给出这个警告:

git filter-branch 有很多陷阱,这些陷阱可能会对预期的历史重写产生不明显的破坏(并且由于它的性能如此糟糕,因此您几乎没有时间调查此类问题)。这些安全和性能问题不能向后兼容修复,因此不建议使用它。请使用替代历史过滤工具,例如git filter-repo。如果您仍然需要使用 git filter-branch,请仔细阅读安全(和性能)以了解 filter-branch 的地雷,然后尽可能合理地避免其中列出的许多危害。

更改作者(或提交者)将需要重写所有历史记录。如果您对此感到满意并认为值得,那么您应该查看git filter-branch。手册页包含几个帮助您入门的示例。另请注意,您可以使用环境变量来更改作者、提交者、日期等的名称——请参阅git 手册页的“环境变量”部分。

具体来说,您可以使用此命令修复所有分支和标签的所有错误作者姓名和电子邮件(来源:GitHub 帮助):

#!/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

使用替代的历史过滤工具git filter-repo,你可以先安装它并git-mailmap根据gitmailmap的格式构造一个。

Proper Name <proper@email.xx> Commit Name <commit@email.xx>

然后使用创建的邮件映射运行 filter-repo:

git filter-repo --mailmap git-mailmap
于 2009-04-15T03:16:42.690 回答
691

一个班轮,但如果您有一个多用户存储库,请小心 - 这会将所有提交更改为具有相同的(新)作者和提交者。

git filter-branch -f --env-filter "GIT_AUTHOR_NAME='Newname'; GIT_AUTHOR_EMAIL='new@email'; GIT_COMMITTER_NAME='Newname'; GIT_COMMITTER_EMAIL='new@email';" HEAD

在字符串中使用换行符(这在 bash 中是可能的):

git filter-branch -f --env-filter "
    GIT_AUTHOR_NAME='Newname'
    GIT_AUTHOR_EMAIL='new@email'
    GIT_COMMITTER_NAME='Newname'
    GIT_COMMITTER_EMAIL='new@email'
  " HEAD
于 2009-04-15T03:22:10.603 回答
602

你也可以这样做:

git filter-branch --commit-filter '
        if [ "$GIT_COMMITTER_NAME" = "<Old Name>" ];
        then
                GIT_COMMITTER_NAME="<New Name>";
                GIT_AUTHOR_NAME="<New Name>";
                GIT_COMMITTER_EMAIL="<New Email>";
                GIT_AUTHOR_EMAIL="<New Email>";
                git commit-tree "$@";
        else
                git commit-tree "$@";
        fi' HEAD

请注意,如果您在 Windows 命令提示符下使用此命令,则需要使用以下命令"代替'

git filter-branch --commit-filter "
        if [ "$GIT_COMMITTER_NAME" = "<Old Name>" ];
        then
                GIT_COMMITTER_NAME="<New Name>";
                GIT_AUTHOR_NAME="<New Name>";
                GIT_COMMITTER_EMAIL="<New Email>";
                GIT_AUTHOR_EMAIL="<New Email>";
                git commit-tree "$@";
        else
                git commit-tree "$@";
        fi" HEAD
于 2009-05-15T19:15:44.667 回答
242

当您没有$HOME/.gitconfig初始化时会发生这种情况。您可以将其修复为:

git config --global user.name "you name"
git config --global user.email you@domain.com
git commit --amend --reset-author

使用 git 版本 1.7.5.4 进行测试。

请注意,这仅修复了最后一次提交。

于 2012-02-16T09:46:05.487 回答
198

如果只有前几个提交的作者不好,您可以git rebase -i使用exec命令和--amend提交在内部完成所有操作,如下所示:

git rebase -i HEAD~6 # as required

它为您提供了可编辑的提交列表:

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

exec ... --author="..."然后在所有作者不好的行之后添加行:

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

保存并退出编辑器(运行)。

这个解决方案的打字时间可能比其他解决方案长,但它是高度可控的——我确切地知道它命中了什么提交。

感谢@asmeurer 的启发。

于 2011-12-08T17:05:03.690 回答
190

对于单个提交:

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

(摘自 asmeurer 的回答)

于 2010-04-26T22:50:54.550 回答
116

Github 有一个不错的解决方案,就是下面的 shell 脚本:

#!/bin/sh

git filter-branch --env-filter '

an="$GIT_AUTHOR_NAME"
am="$GIT_AUTHOR_EMAIL"
cn="$GIT_COMMITTER_NAME"
cm="$GIT_COMMITTER_EMAIL"

if [ "$GIT_COMMITTER_EMAIL" = "your@email.to.match" ]
then
    cn="Your New Committer Name"
    cm="Your New Committer Email"
fi
if [ "$GIT_AUTHOR_EMAIL" = "your@email.to.match" ]
then
    an="Your New Author Name"
    am="Your New Author Email"
fi

export GIT_AUTHOR_NAME="$an"
export GIT_AUTHOR_EMAIL="$am"
export GIT_COMMITTER_NAME="$cn"
export GIT_COMMITTER_EMAIL="$cm"
'
于 2010-10-07T09:54:14.417 回答
84

正如 docgnome 所提到的,重写历史是危险的,并且会破坏其他人的存储库。

但是如果你真的想这样做并且你在一个 bash 环境中(在 Linux 上没问题,在 Windows 上,你可以使用 git bash,它是 git 安装提供的),使用git filter-branch

git filter-branch --env-filter '
  if [ $GIT_AUTHOR_EMAIL = bad@email ];
    then GIT_AUTHOR_EMAIL=correct@email;
  fi;
export GIT_AUTHOR_EMAIL'

为了加快速度,您可以指定要重写的修订范围:

git filter-branch --env-filter '
  if [ $GIT_AUTHOR_EMAIL = bad@email ];
    then GIT_AUTHOR_EMAIL=correct@email;
  fi;
export GIT_AUTHOR_EMAIL' HEAD~20..HEAD
于 2010-08-04T00:52:53.897 回答
82

用于更改最后 N 次提交的作者的单个命令:

git rebase -i HEAD~N -x "git commit --amend --author 'Author Name <author.name@mail.com>' --no-edit"

笔记

  • 替换HEAD~N为参考,直到您要重写提交。这可以是哈希、HEAD~4分支名称、...
  • --no-edit标志确保git commit --amend不要求额外确认
  • 使用时git rebase -i,您可以手动选择更改作者的提交,

您编辑的文件将如下所示:

pick 897fe9e simplify code a little
exec git commit --amend --author 'Author Name <author.name@mail.com>' --no-edit
pick abb60f9 add new feature
exec git commit --amend --author 'Author Name <author.name@mail.com>' --no-edit
pick dc18f70 bugfix
exec git commit --amend --author 'Author Name <author.name@mail.com>' --no-edit

然后,您仍然可以修改一些行以查看要更改作者的位置。这为您在自动化和控制之间提供了一个很好的中间地带:您会看到将要运行的步骤,一旦您保存,所有内容都会立即应用。

请注意,如果您已经使用 和 修复了作者信息git config user.name <your_name>git config user.email <your_email>您还可以使用以下命令:

git rebase -i HEAD~N -x "git commit --amend --reset-author --no-edit"
于 2019-01-25T10:14:33.283 回答
50

您可以将其用作别名,以便执行以下操作:

git change-commits GIT_AUTHOR_NAME "old name" "new name"

或最后 10 次提交:

git change-commits GIT_AUTHOR_EMAIL "old@email.com" "new@email.com" HEAD~10..HEAD

添加到 ~/.gitconfig:

[alias]
    change-commits = "!f() { VAR=$1; OLD=$2; NEW=$3; shift 3; git filter-branch --env-filter \"if [[ \\\"$`echo $VAR`\\\" = '$OLD' ]]; then export $VAR='$NEW'; fi\" $@; }; f "

来源:https ://github.com/brauliobo/gitconfig/blob/master/configs/.gitconfig

希望它是有用的。

于 2012-08-01T23:09:12.633 回答
49

当从另一个作者那里接管一个未合并的提交时,有一种简单的方法来处理这个问题。

git commit --amend --reset-author

于 2016-03-23T22:23:11.657 回答
42

这是@Brian 版本的更详细的版本:

要更改作者和提交者,您可以这样做(在字符串中使用换行符,这在 bash 中是可能的):

git filter-branch --env-filter '
    if [ "$GIT_COMMITTER_NAME" = "<Old name>" ];
    then
        GIT_COMMITTER_NAME="<New name>";
        GIT_COMMITTER_EMAIL="<New email>";
        GIT_AUTHOR_NAME="<New name>";
        GIT_AUTHOR_EMAIL="<New email>";
    fi' -- --all

您可能会遇到以下错误之一:

  1. 临时目录已经存在
  2. 以refs/original开头的 Refs已经存在(这意味着之前已经在存储库上运行了另一个过滤器分支,然后在refs/original
    备份了原始分支引用)

如果您想在出现这些错误的情况下强制运行,请添加--force标志:

git filter-branch --force --env-filter '
    if [ "$GIT_COMMITTER_NAME" = "<Old name>" ];
    then
        GIT_COMMITTER_NAME="<New name>";
        GIT_COMMITTER_EMAIL="<New email>";
        GIT_AUTHOR_NAME="<New name>";
        GIT_AUTHOR_EMAIL="<New email>";
    fi' -- --all

可能需要对该选项进行一些解释-- --all:它使过滤器分支适用于所有参考(包括所有分支)的所有修订。这意味着,例如,标签也被重写并且在重写的分支上可见。

一个常见的“错误”是使用HEAD,这意味着仅过滤当前分支上的所有修订。然后在重写的分支中将不存在任何标签(或其他参考)。

于 2011-12-09T10:23:12.877 回答
34

我应该指出,如果唯一的问题是作者/电子邮件与您平时不同,这不是问题。.mailmap正确的解决方法是在目录的基础上创建一个名为的文件,其中包含如下行

Name you want <email you want> Name you don't want <email you don't want>

从那时起,类似的命令git shortlog将认为这两个名称相同(除非您明确告诉他们不要这样做)。有关更多信息,请参阅http://schacon.github.com/git/git-shortlog.html

这具有此处所有其他解决方案的优势,因为您不必重写历史记录,如果您有上游可能会导致问题,并且始终是意外丢失数据的好方法。

当然,如果您以自己的身份提交了某些内容,并且确实应该是其他人,并且此时您不介意重写历史记录,那么更改提交作者可能是出于归因目的的好主意(在这种情况下,我将您引导至我的其他答案在这里)。

于 2012-02-28T23:57:32.817 回答
25
  1. git rebase -i <sha1 or ref of starting point>

  2. edit用(或e)标记所有要更改的提交

  3. 循环以下两个命令,直到处理完所有提交:

    git commit --amend --reuse-message=HEAD --author="New Author <new@author.email>" ; git rebase --continue

这将保留所有其他提交信息(包括日期)。该--reuse-message=HEAD选项阻止消息编辑器启动。

于 2012-10-04T02:22:52.930 回答
24

我使用以下内容重写整个存储库的作者,包括标签和所有分支:

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

然后,如filter-branch 的 MAN 页面中所述,删除所有备份的原始 refs filter-branch(这是破坏性的,首先备份):

git for-each-ref --format="%(refname)" refs/original/ | \
xargs -n 1 git update-ref -d
于 2011-02-16T15:27:27.147 回答
24

git 的一个更安全的替代品filter-branchfilter-repogit docs here建议的工具。

git filter-repo --commit-callback '
  old_email = b"your-old-email@example.com"
  correct_name = b"Your Correct Name"
  correct_email = b"your-correct-email@example.com"
  
  if commit.committer_email == old_email :
    commit.committer_name = correct_name
    commit.committer_email = correct_email

  if commit.author_email == old_email : 
    commit.author_name = correct_name
    commit.author_email = correct_email
  '

上述命令反映了脚本中使用的逻辑,但使用filter-repo而不是filter-branch.

选项后的代码主体commit-callback基本上是用于处理提交的 python 代码。你可以在这里用 python 编写你自己的逻辑。在此处查看有关commit对象及其属性的更多信息。

由于filter-repo该工具未与 git 捆绑在一起,因此您需要单独安装它。

请参阅先决条件安装指南

如果你有一个 python env >= 3.5,你可以使用pip它来安装它。

pip3 install git-filter-repo

注意filter-repo:强烈建议在新克隆上尝试工具。操作完成后,遥控器也会被移除。阅读更多关于为何在此处移除遥控器的信息。另请阅读内部部分下此工具的限制。

于 2020-04-22T15:03:24.820 回答
21

我调整了这个解决方案,它通过摄取一个简单的author-conv-file(格式与git-cvsimport 相同)来工作。它通过更改author-conv-file所有分支中定义的所有用户来工作。

我们结合使用它cvs2git来将我们的存储库从 cvs 迁移到 git。

即样本author-conv-file

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

剧本:

 #!/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
于 2011-02-04T22:46:26.560 回答
18

我发现提供的版本具有攻击性,特别是如果您提交其他开发人员的补丁,这实际上会窃取他们的代码。

下面的版本适用于所有分支,并分别更改作者和提交者以防止这种情况。

感谢 leif81 的所有选项。

#!/bin/bash

git filter-branch --env-filter '
if [ "$GIT_AUTHOR_NAME" = "<old author>" ];
then
    GIT_AUTHOR_NAME="<new author>";
    GIT_AUTHOR_EMAIL="<youmail@somehost.ext>";
fi
if [ "$GIT_COMMITTER_NAME" = "<old committer>" ];
then
    GIT_COMMITTER_NAME="<new commiter>";
    GIT_COMMITTER_EMAIL="<youmail@somehost.ext>";
fi
' -- --all
于 2012-04-23T08:46:54.910 回答
17
  1. 更改提交author name & emailAmend然后替换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. 另一种方式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
    
于 2016-12-14T15:01:26.633 回答
17

最快、最简单的方法是使用 git rebase 的 --exec 参数:

git rebase -i -p --exec 'git commit --amend --reset-author --no-edit'

这将创建一个如下所示的待办事项列表:

pick ef11092 Blah blah blah
exec git commit --amend --reset-author --no-edit
pick 52d6391 Blah bloh bloo
exec git commit --amend --reset-author --no-edit
pick 30ebbfe Blah bluh bleh
exec git commit --amend --reset-author --no-edit
...

这将自动工作,当你有数百个提交时工作。

于 2018-10-25T16:19:53.250 回答
9

如果您是此存储库的唯一用户,您可以使用(如svick 所写)或/加过滤器脚本(如docgnome answer中引用的文章中所述)或交互式rebase重写历史记录。但是其中任何一个都会从第一次更改提交开始更改修订;这对于任何将他/她的更改基于您的分支预重写的人来说都意味着麻烦。git filter-branchgit fast-exportgit fast-import

恢复

如果其他开发人员的工作不是基于预重写版本,最简单的解决方案是重新克隆(再次克隆)。

或者,他们可以尝试git rebase --pull,如果他们的存储库中没有任何更改,这将快进,或者在重写的提交之上重新设置他们的分支(我们希望避免合并,因为它会永远保持重写前的提交)。所有这一切都假设他们没有提交工作;否则用于git stash隐藏更改。

如果其他开发人员使用功能分支,和/或git pull --rebase不工作,例如因为上游没有设置,他们必须在重写后提交之上重新调整他们的工作。例如,在获取新更改 ( git fetch) 之后,对于master基于 / forked from的分支origin/master,需要运行

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

origin/master@{1}是预重写状态(获取之前),请参阅gitrevisions


另一种解决方案是使用refs/replace/机制,从版本 1.6.5 开始在 Git 中可用。在此解决方案中,您可以替换具有错误电子邮件的提交;那么任何获取'replace' refs 的人(类似于fetch = +refs/replace/*:refs/replace/*refspec 在他们 .git/config的适当位置)都会透明地获得替换,而那些不获取这些 refs 的人会看到旧的提交。

程序是这样的:

  1. 查找所有带有错误电子邮件的提交,例如使用

    $ git log --author=user@wrong.email --all
    
  2. 对于每个错误的提交,创建一个替换提交,并将其添加到对象数据库

    $ 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. 现在您已经更正了对象数据库中的提交,您必须使用git replace命令告诉 git 通过更正的提交来自动透明地替换错误的提交:

    $ git replace <ID of wrong commit> <ID of corrected commit>
    
  4. 最后,列出所有替换以检查此过程是否成功

    $ git replace -l
    

    并检查是否发生更换

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

你当然可以自动化这个过程......好吧,除了使用git replace没有(还)批处理模式之外,你必须为此使用shell循环,或者替换“手动”。

未测试!YMMV。

请注意,您在使用refs/replace/机制时可能会遇到一些粗糙的角落:它是新的,尚未经过很好的测试

于 2010-08-04T09:41:51.647 回答
8

请注意,git 存储了两个不同的电子邮件地址,一个用于提交者(提交更改的人),另一个用于作者(编写更改的人)。

提交者信息不会在大多数地方显示,但您可以使用git log -1 --format=%cn,%ce(或使用show而不是log指定特定提交)来查看它。

虽然更改上一次提交的作者很简单git commit --amend --author "Author Name <email@example.com>",但没有单行或参数可以对提交者信息做同样的事情。

解决方案是(临时或不)更改您的用户信息,然后修改提交,这会将提交者更新为您当前的信息:

git config user.email my_other_email@example.com 
git commit --amend
于 2013-12-05T21:21:22.010 回答
6

如果您要修复的提交是最新的,并且只是其中的几个,您可以使用 和 的组合在配置正确的名称git resetgit stash电子邮件后再次返回提交它们。

序列将是这样的(对于 2 次错误提交,没有待处理的更改):

git config user.name <good name>
git config user.email <good email>
git reset HEAD^
git stash
git reset HEAD^
git commit -a
git stash pop
git commit -a
于 2011-09-30T18:04:00.783 回答
6

将所有提交(包括第一次提交)重置为当前用户和当前时间戳:

git rebase --root --exec "git commit --amend --no-edit --date 'now' --reset-author"
于 2021-12-11T15:22:38.787 回答
5

如果您将 Eclipse 与 EGit 一起使用,那么有一个非常简单的解决方案。
假设:您在本地分支“local_master_user_x”中有提交,由于用户无效,无法将其推送到远程分支“master”。

  1. 签出远程分支'master'
  2. 选择“local_master_user_x”包含更改的项目/文件夹/文件
  3. 右键 - 替换为 - 分支 - 'local_master_user_x'
  4. 再次提交这些更改,这次作为正确的用户并进入本地分支“master”
  5. 推送到远程“主人”
于 2011-08-24T17:54:19.353 回答
5

使用交互式变基,您可以在每次要更改的提交之后放置一个修改命令。例如:

pick a07cb86 Project tile template with full details and styling
x git commit --amend --reset-author -Chead
于 2013-02-26T13:19:47.143 回答
5

我们今天遇到了一个问题,作者姓名中的 UTF8 字符在构建服务器上造成了问题,因此我们不得不重写历史记录来纠正这个问题。采取的步骤是:

第 1 步:按照此处的说明更改您在 git 中的用户名以进行所有未来提交: https ://help.github.com/articles/setting-your-username-in-git/

第 2 步:运行以下 bash 脚本:

#!/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

快速概览:将存储库签出到临时文件,签出所有远程分支,运行将重写历史记录的脚本,强制推送新状态,并告诉所有同事执行 rebase pull 以获取更改。

我们在 OS X 上运行它时遇到了麻烦,因为它以某种方式弄乱了提交消息中的行尾,所以我们不得不在 Linux 机器上重新运行它。

于 2014-10-22T03:32:28.180 回答
5

你的问题真的很常见。请参阅“在 Git 中使用 Mailmap 修复作者列表

为了简单起见,我创建了一个脚本来简化这个过程:git-changemail

将该脚本放在您的路径上后,您可以发出如下命令:

  • 更改当前分支上的作者匹配

    $ git changemail -a old@email.com -n newname -m new@email.com
    
  • 更改 <branch> 和 <branch2> 上的作者和提交者匹配。传递-f给过滤器分支以允许重写备份

    $ git changemail -b old@email.com -n newname -m new@email.com -- -f &lt;branch> &lt;branch2>
    
  • 在 repo 上显示现有用户

    $ git changemail --show-both
    

顺便说一句,在进行更改后,使用以下命令清理过滤器分支中的备份:git-backup-clean

于 2015-01-03T12:19:08.033 回答
4

如果您想(轻松)更改当前分支的作者,我将使用如下内容:

# update author for everything since origin/master
git rebase \
  -i origin/master \
  --exec 'git commit --amend --no-edit --author="Author Name <author.name@email.co.uk>"'
于 2020-05-05T14:51:48.093 回答
3

我也想添加我的示例。我想用给定的参数创建一个 bash_function。

这适用于 mint-linux-17.3

# $1 => email to change, $2 => new_name, $3 => new E-Mail

function git_change_user_config_for_commit {

 # defaults
 WRONG_EMAIL=${1:-"you_wrong_mail@hello.world"}
 NEW_NAME=${2:-"your name"}
 NEW_EMAIL=${3:-"new_mail@hello.world"}

 git filter-branch -f --env-filter "
  if [ \$GIT_COMMITTER_EMAIL = '$WRONG_EMAIL' ]; then
    export GIT_COMMITTER_NAME='$NEW_NAME'
    export GIT_COMMITTER_EMAIL='$NEW_EMAIL'
  fi
  if [ \$GIT_AUTHOR_EMAIL = '$WRONG_EMAIL' ]; then
    export GIT_AUTHOR_NAME='$NEW_NAME'
    export GIT_AUTHOR_EMAIL='$NEW_EMAIL'
  fi
 " --tag-name-filter cat -- --branches --tags;
}
于 2017-09-28T14:15:37.357 回答
3

试试这个。它将执行与上述相同的操作,但交互方式。

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

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

于 2018-06-05T20:04:42.033 回答
2

如果您是此 repo 的唯一用户,或者您不关心可能会破坏其他用户的 repo,那么可以。如果您推送了这些提交并且它们存在于其他地方可以访问它们的地方,那么不,除非您不关心破坏其他人的存储库。问题是通过更改这些提交,您将生成新的 SHA,这将导致它们被视为不同的提交。当其他人试图拉入这些更改的提交时,历史就不同了,而且很疯狂。

此页面http://inputvalidation.blogspot.com/2008/08/how-to-change-git-commit-author.html描述了如何做到这一点。(我没试过这个所以YMMV)

于 2010-08-04T00:40:57.563 回答
2

我想为@Rognon 答案的修改做出贡献。如果所选答案或其他答案对您不起作用(在我的特定问题中就是这种情况),此答案只是另一种选择:

目标:您将在所有历史中使用正确的作者修复一位或多位作者,并且您将获得没有重复的干净历史。此方法通过用“干净”分支替换“主”分支来工作(它不使用合并/变基)

注意:使用“主”存储库的任何人都可能需要在推送之前再次检出它(在执行这些步骤之后),因为合并可能会失败。

我们将使用一个名为“clean”的新分支来执行操作(假设您要修复“master”):

git checkout -b clean

(确保您在“干净”分支中git branch:)

修改以下脚本(替换电子邮件地址和姓名)。请注意,此脚本需要两个错误的电子邮件/作者(例如),因此如果您只需要修复一个作者,您可以删除条件的第二部分或保持原样(因为它将被忽略,因为它不会t 匹配)。

执行脚本。

#/bin/bash

git filter-branch --force --commit-filter '
        if [ "$GIT_COMMITTER_EMAIL" = "wrong1@example.com" -o "$GIT_COMMITTER_EMAIL" = "wrong2@example.com" ];
        then
                export GIT_COMMITTER_NAME="John Doe";
                export GIT_AUTHOR_NAME="John Doe";
                export GIT_COMMITTER_EMAIL="correct@example.com";
                export GIT_AUTHOR_EMAIL="correct@example.com";
        fi;
        git commit-tree "$@"
' --tag-name-filter cat -- --all

它必须报告:Ref 'refs/heads/clean' was rewritten。如果它报告“未更改”,则脚本中输入的电子邮件可能是错误的。

通过以下方式确认历史记录已更正:git log

如果您使用的是github/gitlab(推荐 = 安全):

  1. 在远程创建“干净”分支:

git push --set-upstream origin clean

  1. 将“干净”分支设置为默认分支
  2. 删除“master”(在执行此操作之前确保一切都按预期进行)。
  3. 在“clean”分支中创建一个新的分支“master”。
  4. 确认一切正常后,您现在可以删除“干净”分支(或者您可以重命名它)。

如果不使用 github/gitlab或者您更喜欢通过命令执行此操作:

  1. 从本地删除主分支:

git branch -d master

  1. 重命名分支:

git branch -m clean master

  1. 推它(确保你的“主人”不受保护)

git push --force origin master

于 2020-01-04T04:14:19.073 回答
2

对于所有提交,我的解决方案:

git rebase -i --root -x "git commit --amend --author 'bedorlan <bedorlan@gmail.com>' --no-edit"
于 2021-09-27T16:56:22.463 回答
1
git rebase -i YOUR_FIRTS_COMMIT_SHA^

while true; do git commit --amend --author="Name Surname <email@example.com>" --no-edit && git rebase --continue; done

变基完成后按 ^C # (循环将不断更新最后一次提交)

于 2016-12-07T22:53:50.563 回答
1

上面的所有答案都重写了存储库的历史。只要多个作者没有使用要更改的名称,特别是如果存储库已共享并且提交是旧的,我更愿意使用.mailmap,记录在https://git-scm.com/docs/git-短日志。它允许将不正确的名称/电子邮件映射到正确的名称/电子邮件,而无需修改回购历史记录。您可以使用以下行:

Proper Name <proper@email.xx> <root@localhost>
于 2019-08-30T20:19:20.010 回答
1

我试过上面的脚本对我不起作用,这解决了我的问题:

使用 Git 的“过滤器分支”命令。它允许您使用脚本批处理(可能很大)数量的提交。您可以在存储库中运行以下示例脚本(填写新旧电子邮件和名称的实际值):

git filter-branch --env-filter '
WRONG_EMAIL="wrong@example.com"
NEW_NAME="New Name Value"
NEW_EMAIL="correct@example.com"

if [ "$GIT_COMMITTER_EMAIL" = "$WRONG_EMAIL" ]
then
    export GIT_COMMITTER_NAME="$NEW_NAME"
    export GIT_COMMITTER_EMAIL="$NEW_EMAIL"
fi
if [ "$GIT_AUTHOR_EMAIL" = "$WRONG_EMAIL" ]
then
    export GIT_AUTHOR_NAME="$NEW_NAME"
    export GIT_AUTHOR_EMAIL="$NEW_EMAIL"
fi
' --tag-name-filter cat -- --branches --tags

在此处查看更多详细信息

于 2021-10-24T13:08:48.483 回答
0

对于 windows 下的用户,也可以使用git-rocket-filter工具。

文档中

更改提交作者姓名和电子邮件:

git-rocket-filter --branch TestBranch --commit-filter '
    if (commit.AuthorName.Contains("Jim")) {   
        commit.AuthorName = "Paul"; 
        commit.AuthorEmail = "paul@company.com"; 
    }
于 2019-10-30T10:08:23.380 回答
-1

这不是您问题的答案,而是您将来可以用来避免这种情况的脚本。它利用Git 2.9 版以来可用的全局挂钩来根据您所在的目录检查您的电子邮件配置:

#!/bin/sh
PWD=`pwd`
if [[ $PWD == *"Ippon"* ]] # 1)
then
  EMAIL=$(git config user.email)
  if [[ $EMAIL == *"Work"* ]] # 2)
  then
    echo "";
  else
    echo "Email not configured to your Work email in the Work directory.";
    git config user.email "youremail@youremail.com"
    echo "Git email configuration has now been changed to \"$(git config user$
    echo "\nPlease run your command again..."
    echo ''
    exit 1
  fi;
elif [[ $PWD == *"Personal"* ]]
then
  EMAIL=$(git config user.email)
  if [[ $EMAIL == "youremail@youremail.com" ]]
  then
    echo "";
  else
    echo "Email is not configured to your personal account in the Personal di$
    git config user.email "youremail@youremail.com"
    echo "Git email configuration has now been changed to \"$(git config user$
    echo "\nPlease run your command again..."
    echo ''
    exit 1;
  fi;
fi; 

它检查您当前的工作目录,然后验证您的 git 是否配置为正确的电子邮件。如果没有,它会自动更改它。在此处查看完整的详细信息。

于 2016-12-15T15:04:56.247 回答