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


170

我已经对Github上的一个项目进行了很多提交,但是我意识到我没有在我当前用来进行提交的计算机上设置正确的电子邮件和提交者全名,因此用户的头像和电子邮件地址不在那里。

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



在更改我的GitHub帐户上的电子邮件地址后,我遇到了这种情况。除了使用git命令行(而不是GitHub桌面)从本地git repo推送代码更改之外,我还使用GitHub Web界面直接从远程git repo编辑文本和托管文件。新的电子邮件地址仅传播到后一种动作引起的提交,而不传播到前者。
罗伯·约翰

Answers:


243

您可以添加以下别名:

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"

或仅最近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


13
git change-commits GIT_COMMITTER_EMAIL "old@example.com" "new@example.com"可以更改提交者的电子邮件。
劳伦特

19
修复了ubuntu上的“ eval:[[:未找到””并添加确认的问题change-commits = "!f() { VAR1=$1; VAR='$'$1; OLD=$2; NEW=$3; echo \"Are you sure for replace $VAR $OLD => $NEW ?(Y/N)\";read OK;if [ \"$OK\" = 'Y' ] ; then shift 3; git filter-branch --env-filter \"if [ \\\"${VAR}\\\" = '$OLD' ]; then export $VAR1='$NEW';echo 'to $NEW'; fi\" $@; fi;}; f "
qxo

9
git:'change-commits'不是git命令。参见'git --help'。表示您尚未将别名添加到git配置中。例如git config -e
Wayne

2
这只是使所有提交与我要更改的电子邮件重复。似乎没有重写历史记录。@Olivier Verdier的解决方案为我工作。
杰克·威尔逊

6
用不同的输入连续执行两次会导致:Cannot create a new backup. A previous backup already exists in refs/original/
theonlygusti

97

解决方案已经存在:在Git中更改作者和提交者名称以及多次提交的电子邮件

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

4
这不会更改分支的所有提交(整个历史记录)的作者名称吗?
哈森

2
是的,这将更改所有对新作者信息的提交。
ewall

9
请把问题标记为重复,而不是复制粘贴答案。
Givanse 2014年

2
如果我没有指定旧名称或旧电子邮件怎么办?git说“不允许空标识符<>”
Griffan 2015年

我运行了此命令,现在我的存储库将不会推入或拉出git服务器。
耶稣H

46

如果你已经迫使一些你提交到公共仓库的,你希望这样做,否则会令主人的历史的替代版本,其他人可能已经使用。“不要越过溪流……那会很糟糕……”

就是说,如果只是您对本地存储库所做的提交,那么一定要在推送到服务器之前解决此问题。您可以将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

5
这很完美,而用绿色标记的答案却没有
jmary 18'Dec

之后,可能需要使用清除备份git update-ref -d refs/original/refs/heads/master,请参见< stackoverflow.com/a/7654880/333403 >。
cknoll

仅供参考:如果您有多个不正确的姓名/电子邮件,则可能需要多次运行。如果发生这种情况,它将为您抱怨并出现以下错误:A previous backup already exists in refs/original/在这种情况下,请使用新电子邮件重新运行它,并-f在--commit-filter之前添加一个。自行决定使用。-f如果不知道正在做什么,通常会很危险。
Chuck

19

应用奥利维尔·韦迪耶的答案后:

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

上面的命令(注意加号)也强制在原始仓库上重写历史记录。请谨慎使用!


为我工作,也正确地改写了历史。
Xeverous

10
这将重写所有提交-无论是谁编写的。请谨慎使用。
Bhavin Doshi

14

https://help.github.com/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 push之后,请确保在git的Web门户上看到更新。如果提交仍未链接到我的帐户,则在提交旁边显示默认的缩略图图像,并且未反映在我的贡献时间轴图表上,请转到提交网址,并在网址末尾附加.patch,然后验证名称和电子邮件是正确的。


虽然从理论上讲这可以回答问题,但最好在此处包括答案的基本部分,并提供链接以供参考。
jhpratt

1
这是唯一重写所有分支的程序。
布鲁诺·泽尔

6

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

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

5
-bash:!f:未找到事件
Saiyine

终端最有可能自动将内容转义的问题
Andrei Savin

3

考虑到使用的git-filter-branch没有希望的,做同样的事情在git的过滤器回购(您可能需要与第一次安装它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")'

如果存储库是原始的,没有远程存储,则必须添加--force以强制重写。(您可能需要在执行此操作之前创建存储库的备份。)

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

有关更多高级功能,请参阅“名称和电子邮件的过滤”

PS被盗并已从https://stackoverflow.com/a/59591928/714907进行了改进。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.