如何更改多个提交的作者和提交者名称/电子邮件?

如何更改一系列提交的作者?

1047609 次浏览

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

git filter分支有太多的陷阱,可能会对预期的历史重写产生不明显的篡改(并且可能会让您几乎没有时间来调查此类问题,因为它具有如此糟糕的性能)。这些安全和性能问题无法向后兼容修复,因此,不推荐使用它。请使用替代的历史过滤工具,例如git filter-repo开发完成。如果您仍然需要使用git filter分支,请仔细阅读安全(和性能)以了解filter分支的地雷,然后保持警惕,尽可能多地避免那里列出的危害。

更改作者(或提交者)需要重写所有的历史记录。如果你对此没意见并且认为值得,那么你应该查看git过滤分支。手册页包括几个示例来帮助你入门。还要注意,你可以使用环境变量来更改作者的名称,提交者,日期等-请参阅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" ]thenexport GIT_COMMITTER_NAME="$CORRECT_NAME"export GIT_COMMITTER_EMAIL="$CORRECT_EMAIL"fiif [ "$GIT_AUTHOR_EMAIL" = "$OLD_EMAIL" ]thenexport GIT_AUTHOR_NAME="$CORRECT_NAME"export GIT_AUTHOR_EMAIL="$CORRECT_EMAIL"fi' --tag-name-filter cat -- --branches --tags

对于使用替代历史过滤工具git filter-repo开发完成,您可以首先安装它并根据gitmail地图的格式构造一个git-mailmap

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

然后使用创建的mail map运行filter-repo:

git filter-repo --mailmap git-mailmap

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

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

你也可以这样做:

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

请注意,如果您在Windows命令提示符中使用此命令,则需要使用"而不是'

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

注意:此答案更改SHA1,因此在已推送的分支上使用它时要小心。如果您只想修复名称的拼写或更新旧电子邮件,Git允许您这样做,而无需使用.mailmap重写历史记录。请参阅我的其他答案

使用rebase

首先,如果您还没有这样做,您可能希望在git-config中修复您的名称:

git config --global user.name "New Author Name"git config --global user.email "<email@address.example>"

这是可选的,但它也将确保重置提交者名称,假设这是您需要的。

要使用rebase重写一系列提交的元数据,请执行

git rebase -r <some commit before all of your bad commits> \--exec 'git commit --amend --no-edit --reset-author'

--exec将在每次提交重写后运行git commit步骤(就像重复运行git commit && git rebase --continue一样)。

如果您还想更改您的第一次提交(也称为“root”提交),则必须将--root添加到rebase调用中。

这会将提交者和作者都更改为user.name/user.email配置。如果您不想更改该配置,可以使用--author "New Author Name <email@address.example>"而不是--reset-author。请注意,这样做将没有更新提交者-只有作者。

单一提交

如果你只是想更改最近的提交,则不需要rebase。只需修改提交:

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

整个项目历史

git rebase -r --root --exec "git commit --amend --no-edit --reset-author"

对于较旧的Git客户端(2020年7月之前)

-r,--rebase-merges对您来说可能不存在。作为替换,您可以使用-p。请注意,-p有严重的问题,现在不建议使用。

对于单个提交:

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

(摘自作者的回答)

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

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

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

但是如果你真的想这样做,并且你在bash环境中(在Linux没有问题,在Windows上,你可以使用git bash,这是git安装提供的),使用git过滤分支

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

如果您是此存储库的唯一用户,您可以使用#0(作为斯维克写道)、#1/#2加上过滤器脚本(如docgnome答案中引用的文章所述)或交互式rebase改写历史。但是,其中任何一个都会从第一次更改的提交开始更改修订;这对任何基于您的分支预重写的更改的人来说都意味着麻烦。

恢复

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

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

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

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

这里origin/master@{1}是预重写状态(在提取之前),参见修改版本


替代解决方案是使用Git 1.6.5版以来的引用/替换/机制。在这个解决方案中,你为有错误电子邮件的提交提供替换;然后任何获取“替换”引用的人(类似于他们.git/config中适当位置的fetch = +refs/replace/*:refs/replace/* refspec)将透明地获得替换,而那些没有获取这些引用的人将看到旧的提交。

程序是这样的:

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

    $ 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

    并检查是否有更换

    $ 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.

GitHub最初有一个不错的解决方案(断链),它是以下外壳脚本:

#!/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.example" ]thencn="Your New Committer Name"cm="Your New Committer Email"fiif [ "$GIT_AUTHOR_EMAIL" = "your@email.to.match.example" ]thenan="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"'

我改编了这个解决方案,它通过摄取一个简单的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

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

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

然后,如过滤器分支的城域网页中所述,删除filter-branch备份的所有原始引用(这是破坏性的,首先备份):

git for-each-ref --format="%(refname)" refs/original/ | \xargs -n 1 git update-ref -d

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

  1. 检查远程分支'master'
  2. 选择“local_master_user_x”包含更改的项目/文件夹/文件
  3. 右键单击-替换为-分支-“local_master_user_x”
  4. 再次提交这些更改,这次作为正确的用户并进入本地分支'master'
  5. 推送到远程“主”

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

序列将是这样的(对于2个错误的提交,没有未决的更改):

git config user.name <good name>git config user.email <good email>git reset HEAD^git stashgit reset HEAD^git commit -agit stash popgit commit -a

在只有前几个提交有坏作者的情况下,您可以使用exec命令和--amend提交在git rebase -i中执行此操作,如下所示:

git rebase -i HEAD~6 # as required

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

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

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

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

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

这个解决方案可能比其他一些解决方案要长,但它是高度可控的-我确切地知道它会遇到什么提交。

感谢@asmeurer的灵感。

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

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

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

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

  1. 临时目录已存在
  2. 参考/原文开头的引用已经存在
    (这意味着之前在存储库上运行了另一个filter分支,然后原始分支引用备份在参考/原文

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

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

可能需要对-- --all选项进行一些解释:它使filter分支在所有裁判上的所有修订(包括所有分支)上工作。这意味着,例如,标签也被重写,并且在重写的分支上可见。

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

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

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

使用Git版本1.7.5.4测试。

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

我应该指出,如果唯一的问题是作者/电子邮件与您通常的不同,这不是问题。正确的解决方法是在目录的底部创建一个名为.mailmap的文件,其行如下

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

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

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

当然,如果你以自己的身份提交了一些东西,而它确实应该是别人,并且你不介意在这一点上重写历史,那么更改提交作者可能是一个好主意(在这种情况下,我将引导你到我的另一个答案这里)。

我发现呈现的版本非常激进,特别是如果您从其他开发人员提交补丁,这基本上会窃取他们的代码。

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

所有选项的leif81的荣誉。

#!/bin/bash
git filter-branch --env-filter 'if [ "$GIT_AUTHOR_NAME" = "<old author>" ];thenGIT_AUTHOR_NAME="<new author>";GIT_AUTHOR_EMAIL="<youmail@somehost.ext>";fiif [ "$GIT_COMMITTER_NAME" = "<old committer>" ];thenGIT_COMMITTER_NAME="<new commiter>";GIT_COMMITTER_EMAIL="<youmail@somehost.ext>";fi' -- --all

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

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

希望有用。

  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选项阻止消息编辑器启动。

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

pick a07cb86 Project tile template with full details and stylingx git commit --amend --reset-author -Chead

请注意,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.comgit commit --amend

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

第1步:根据此处的说明,在git中更改您未来提交的用户名:https://help.github.com/articles/setting-your-username-in-git/

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

#!/bin/sh
REPO_URL=ssh://path/to/your.gitREPO_DIR=rewrite.tmp
# Clone the repositorygit clone ${REPO_URL} ${REPO_DIR}
# Change to the cloned repositorycd ${REPO_DIR}
# Checkout all the remote branches as local tracking branchesgit 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 OSXgit filter-branch --env-filter 'OLD_EMAIL="me@something.com"CORRECT_NAME="New Me"
if [ "$GIT_COMMITTER_EMAIL" = "$OLD_EMAIL" ]thenexport GIT_COMMITTER_NAME="$CORRECT_NAME"fiif [ "$GIT_AUTHOR_EMAIL" = "$OLD_EMAIL" ]thenexport GIT_AUTHOR_NAME="$CORRECT_NAME"fi' --tag-name-filter cat -- --branches --tags
# Force push the rewritten branches + tags to the remotegit push -f
# Remove all knowledge that we did somethingrm -rf ${REPO_DIR}
# Tell your colleagues to `git pull --rebase` on all their local remote tracking branches

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

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

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

为了简单起见,我创建了一个脚本来简化这个过程:修改邮箱

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

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

    $ 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

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

git commit --amend --reset-author

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

rebase完成后按^C#(循环将继续更新最后一次提交)

  1. 将提交author name & email更改为Amend,然后替换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

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

#!/bin/shPWD=`pwd`if [[ $PWD == *"Ippon"* ]] # 1)thenEMAIL=$(git config user.email)if [[ $EMAIL == *"Work"* ]] # 2)thenecho "";elseecho "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 1fi;elif [[ $PWD == *"Personal"* ]]thenEMAIL=$(git config user.email)if [[ $EMAIL == "youremail@youremail.com" ]]thenecho "";elseecho "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是否配置为正确的电子邮件。如果没有,它会自动更改它。查看完整的详细信息这里

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

这适用于mint-linux-17.3

# $1 => email to change, $2 => new_name, $3 => new E-Mail
function git_change_user_config_for_commit {
# defaultsWRONG_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' ]; thenexport GIT_COMMITTER_NAME='$NEW_NAME'export GIT_COMMITTER_EMAIL='$NEW_EMAIL'fiif [ \$GIT_AUTHOR_EMAIL = '$WRONG_EMAIL' ]; thenexport GIT_AUTHOR_NAME='$NEW_NAME'export GIT_AUTHOR_EMAIL='$NEW_EMAIL'fi" --tag-name-filter cat -- --branches --tags;}

试试这个。它的作用和上面提到的一样,但是是交互式的。

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

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

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

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

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

pick ef11092 Blah blah blahexec git commit --amend --reset-author --no-editpick 52d6391 Blah bloh blooexec git commit --amend --reset-author --no-editpick 30ebbfe Blah bluh blehexec git commit --amend --reset-author --no-edit...

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

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

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

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

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

pick 897fe9e simplify code a littleexec git commit --amend --author 'Author Name <author.name@mail.example>' --no-editpick abb60f9 add new featureexec git commit --amend --author 'Author Name <author.name@mail.example>' --no-editpick dc18f70 bugfixexec git commit --amend --author 'Author Name <author.name@mail.example>' --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"

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

Proper Name <proper@email.xx> <root@localhost>

对于Windows下的那些,您也可以使用git火箭过滤器工具。

留档

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

git-rocket-filter --branch TestBranch --commit-filter 'if (commit.AuthorName.Contains("Jim")) {commit.AuthorName = "Paul";commit.AuthorEmail = "paul@company.com";}

我想修改@Rognon的答案。这个答案只是另一个选择,以防所选答案或其他答案不适合你(在我的特定问题中是这样):

目标:你将在ALL历史记录中用正确的作者修复一个或多个作者,并且你将获得一个没有重复的干净历史记录。此方法的工作原理是将“主”分支替换为“干净”分支(它不使用合并/rebase)

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

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

git checkout -b clean

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

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

执行脚本。

#/bin/bash
git filter-branch --force --commit-filter 'if [ "$GIT_COMMITTER_EMAIL" = "wrong1@example.com" -o "$GIT_COMMITTER_EMAIL" = "wrong2@example.com" ];thenexport 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/github/github开发环境(推荐=安全):

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

git push --set-upstream origin clean

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

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

  1. 从本地删除主分支:

git branch -d master

  1. 重命名分支:

git branch -m clean master

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

git push --force origin master

gitfilter-branch的更安全的替代方案是git docs这里建议的filter-repo工具。

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_namecommit.committer_email = correct_email
if commit.author_email == old_email :commit.author_name = correct_namecommit.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工具。操作完成后也会删除遥控器。阅读更多关于为什么删除遥控器的信息这里。另请阅读内部部分下此工具的限制。

如果你想(轻松地)更改当前分支的作者,我会使用这样的东西:

# update author for everything since origin/mastergit rebase \-i origin/master \--exec 'git commit --amend --no-edit --author="Author Name <author.name@email.co.uk>"'

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

git rebase -i --root -x "git commit --amend --author 'bedorlan <bedorlan@gmail.com>' --no-edit"

我试过上面的脚本,它不适合我,这解决了我的问题:

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

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" ]thenexport GIT_COMMITTER_NAME="$NEW_NAME"export GIT_COMMITTER_EMAIL="$NEW_EMAIL"fiif [ "$GIT_AUTHOR_EMAIL" = "$WRONG_EMAIL" ]thenexport GIT_AUTHOR_NAME="$NEW_NAME"export GIT_AUTHOR_EMAIL="$NEW_EMAIL"fi' --tag-name-filter cat -- --branches --tags

查看更多详情这里

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

git rebase --root --exec "git commit --amend --no-edit --date 'now' --reset-author"

filter-repo的单行代码:

您可以使用#0中的回调功能(建议替换filter-branch)来更改与所有提交关联的名称和电子邮件:

git filter-repo --name-callback 'return b"New Name"' --email-callback 'return b"newemail@gmail.com"'

这比使用filter-branch的解决方案更高性能,也可能更可靠。

请注意,上面的命令更改了所有提交的作者(和提交者),如果您想有效地“编辑”某个作者,并且只修改该特定作者的提交,请使用--commit-callback选项,如下所示:

git filter-repo --commit-callback 'old_email = b"oldemail@gmail.com"new_email = b"newemail@gmail.com"new_name = b"New Author"
if commit.author_email == old_email:commit.author_email = new_emailcommit.author_name = new_name
if commit.committer_email == old_email:commit.committer_email = new_emailcommit.committer_name = new_name'

(只需将上面命令中的old_emailnew_emailnew_name变量更改为正确的值。)