Git,重写之前提交的用户名和电子邮件

我已经在Github上提交了一堆提交到一个项目,但我意识到我没有在我目前用于提交的计算机上设置正确的电子邮件和提交者全名,因此用户的头像和电子邮件地址不存在。

我如何重写所有过去提交的电子邮件和用户名?

107089 次浏览

看到在这里:

git filter-branch -f --env-filter \
"GIT_AUTHOR_NAME='Newname'; GIT_AUTHOR_EMAIL='newemail'; \
GIT_COMMITTER_NAME='committed-name'; GIT_COMMITTER_EMAIL='committed-email';" HEAD

如果你已经将你的一些提交推到公共存储库,你做想要这样做,或者它会创建一个其他可能使用过的主历史记录的替代版本。“不要过河……那就糟了……”

也就是说,如果只是提交到本地存储库,那么务必在推送到服务器之前修复这个问题。你可以使用git filter-branch命令和--commit-filter选项,所以它只编辑与你的错误信息匹配的提交,就像这样:

git filter-branch --commit-filter '
if [ "$GIT_AUTHOR_EMAIL" = "wrong_email@wrong_host.local" ];
then
GIT_AUTHOR_NAME="Your Name Here (In Lights)";
GIT_AUTHOR_EMAIL="correct_email@correct_host.com";
git commit-tree "$@";
else
git commit-tree "$@";
fi' HEAD

你可以添加这个别名:

git config --global 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"

修改作者名称。

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

别名:

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

在应用Olivier Verdier的答案后:

git filter-branch -f --env-filter \
"GIT_AUTHOR_NAME='Newname'; GIT_AUTHOR_EMAIL='newemail'; \
GIT_COMMITTER_NAME='committed-name'; GIT_COMMITTER_EMAIL='committed-email';" HEAD

...要在原始存储库使用上推送更改的历史记录:

git push origin +yourbranch

上面的命令(注意加号)也会改写原始回购的历史。请谨慎使用!

再次,警告:这将使所有提交的Newname/newemail提交!这种情况是,您有一个回购,其中只有一个作者错误地使用了不同的身份,您希望修复它。

对于那些只想要简单的复制粘贴版本(除了更新电子邮件和姓名):

git config 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 "
git change-commits GIT_AUTHOR_NAME "<Old Name>" "<New Name>" -f
git change-commits GIT_AUTHOR_EMAIL <old@email.com> <new@email.com> -f
git change-commits GIT_COMMITTER_NAME "<Old Name>" "<New Name>" -f
git change-commits GIT_COMMITTER_EMAIL <old@email.com> <new@email.com> -f

https://help.github.jp/enterprise/2.11/user/articles/changing-author-info/

#!/bin/sh


git filter-branch --env-filter '


OLD_EMAIL="oldEmail@xxx-MacBook-Pro.local"
CORRECT_NAME="yourName"
CORRECT_EMAIL="yourEmail"


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推送后,确保在git的门户网站上看到更新。如果提交仍然没有链接到我的帐户,在提交旁边显示默认的缩略图,并且它没有反映在我的贡献时间表上,转到提交url并在url的末尾附加.patch,并验证名称和电子邮件是正确的。

考虑到git-filter-branch的使用是不是想要的,要在git-filter-repo中做同样的事情(你可能需要先用pip install git-filter-repo安装它):

git-filter-repo --name-callback 'return name.replace(b"OldName", b"NewName")' --email-callback 'return email.replace(b"old@email.com", b"new@email.com")'

如果存储库是原始的,w/o远程,你将不得不添加--force来强制重写。(在执行此操作之前,您可能需要创建回购的备份。)

如果你不想保留引用(它们将显示在Git GUI的分支历史中),你必须添加--replace-refs delete-no-add

有关更高级的特性,请参见“姓名过滤&电子邮件”

附注:从https://stackoverflow.com/a/59591928/714907中偷来并改进。

已经给出的答案是完整的。但你确定,你需要这些吗?如。我也遇到过类似的问题,但在这种情况下,答案是多余的。我的案例和解决方案如下:

假设你有两个电子邮件id, no_longer_want@gmail.comwant@gmail.com。有可能之前的提交是通过no_longer_want@gmail.com,这不是你想要的电子邮件id。在这种情况下,一个选择是简单地将want@gmail.com链接到你的GitHub帐户。

怎么做呢?

在设置页面的电子邮件部分找到添加电子邮件的选项。

enter image description here

还失去了吗?

github页面中提到的前三个步骤就足够了。

注意:

  1. Github支持单个Github帐户的多个电子邮件id。
  2. 由于您没有替换电子邮件id,而只是添加了一个新的电子邮件id,通过两个电子邮件id提交的文件都链接到您的Github帐户。
  3. 没有必要将want@gmail.com设置为主要电子邮件id。

如果你主要关心本地回购显示名称,重写历史记录的另一种方法是.mailmap file,它基本上是一个名称和电子邮件列表。例如,在repo的根目录下放置.mailmap文件:

Tamika Page <tamika@somejob.com>
Orlando Cervantes <orlando.cervantes@otherjob.com> Orlando Jackson <orlando.jackson@otherjob.com>
Jared Michael <jared.michael@gmail.com> <jared@desktop.(none)>

将导致归属于tamkia@somejob.com的任何提交都显示为Tamika Page,而不管提交者名称如何,归属于Orlando Jackson <orlando.jackson@otherjob.com>的提交显示为Orlando Cervantes,而烦人的<jared@desktop.(none)>提交则归属于jared.michael@gmail.com。有关详细信息,请查看此特性的git文档 -由于它是内置在git中,因此它应该适用于任何新的git客户端。

这里有一个很大的警告:虽然它在官方git客户端中已经被支持了很长一段时间,但在各种git实现中,特别是大的web接口,并不能保证得到支持——参见这个问题,关于GitHub是否尊重它的共识是混合的,但似乎是负面的。不幸的是,我在GitHubGitLab上进行了快速测试回购,似乎都没有注意到.mailmap

正如@paradocslover的回答中提到的,服务有它们自己的接口来做类似的事情,但你必须为每个服务设置接口,而且它根本不会影响你的本地副本。因为.mailmap是回购的一部分,所以它在本地为任何克隆你的回购的人工作(你可以克隆上面链接的回购自己看看),但它似乎不会显示在我测试的web界面中。

当然,在某些情况下,您确实希望重写历史,但这可能是相当有侵略性的,并附带所有标准的警告,因此在某些情况下,有这个选项是很好的,这可能就足够了,特别是在重写不实际的情况下。