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


当前回答

对于windows下的用户,也可以使用git火箭过滤器工具。

根据文档:

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

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

其他回答

对于单个提交:

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

(摘自阿斯梅勒的回答)

注意:这个答案会改变SHA1,所以在已经推送的分支上使用它时要小心。如果你只想修复一个名字的拼写或更新一封旧邮件,Git可以让你不用使用.mailmap重写历史。

使用回扣

首先,如果您还没有这样做,您可能需要在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将在每次提交被重写后运行gitcommit步骤(就像您运行gitcommit&&gitrebase一样——重复继续)。

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

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

单次提交

如果您只想更改最近的提交,则无需重新设置基准。只需修改承诺:

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

整个项目历史

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

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

-r、 --您可能不存在重基合并。作为替换,可以使用-p。请注意,-p存在严重问题,现已弃用。

git过滤器分支的一个更安全的替代方案是git文档建议的过滤器回购工具。

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
  '

上述命令反映了此脚本中使用的逻辑,但使用过滤器repo而不是过滤器分支。

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

由于filter repo工具未与git捆绑,您需要单独安装它。

请参阅先决条件和安装指南

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

pip3 install git-filter-repo

注意:强烈建议在新克隆上尝试使用过滤器回购工具。操作完成后,也会移除遥控器。阅读更多有关为什么删除遥控器的信息。另请阅读INTERNALS部分中此工具的限制。

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

但是,如果您真的想这样做,并且您处于bash环境中(在Linux和Windows中没有问题,您可以使用git bash,这是安装git时提供的),请使用gitfilter分支:

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

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

我们将其与cvs2git结合使用,将存储库从cvs迁移到git。

即示例作者conv文件

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