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


当前回答

如果您是该存储库的唯一用户,则可以使用gitfilter分支(如svick所写)、git快速导出/git快速导入加上过滤脚本(如docgnome answer中引用的文章所述)或交互式rebase重写历史。但其中任何一项都会从最初更改的承诺开始更改修订;这对任何基于分支预重写的更改的人来说都意味着麻烦。

回收,回收

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

或者,他们可以尝试gitrebase--pull,如果他们的存储库中没有任何更改,这将加快速度,或者在重新编写的提交之上重新设置分支的基础(我们希望避免合并,因为这将永远保留预重写的commit)。所有这一切都假设他们没有未经许可的工作;否则,使用gitstash来隐藏更改。

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

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

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


另一种解决方案是使用refs/replace/mechanism,从1.6.5版开始,Git中就提供了这种机制。在该解决方案中,您可以替换电子邮件错误的提交;那么,任何获取“replace”ref的人(比如fetch=+refs/replace/*:refs/replace/*refspec位于其.git/config中的适当位置)都将透明地获取替换,而那些不获取这些ref的人将看到旧的提交。

程序大致如下:

查找包含错误电子邮件的所有提交,例如使用$git日志--作者=user@wrong.email--全部对于每个错误的提交,创建一个替换提交,并将其添加到对象数据库$git cat文件-p<错误提交的ID>|sed-e的/user@wrong\.电子邮件/user@example.com/g'>tmp.txt$git哈希对象-t提交-w tmp.txt<已更正提交的ID>既然您已经纠正了对象数据库中的提交,您必须告诉git使用git replace命令自动透明地用纠正的提交替换错误的提交:$git替换<错误提交的ID><更正提交的ID最后,列出所有替代品,以检查此过程是否成功$git替换-l并检查是否进行了更换$git日志--作者=user@wrong.email--全部

您当然可以自动执行此过程。。。好吧,除了使用gitreplace,它还没有批处理模式,所以您必须使用shell循环,或者手动替换。

未测试!YMMV。

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

其他回答

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

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

虽然更改上一次提交的作者与gitcommit一样简单--修改--author“作者名称”<email@example.com>“,没有一个liner或argument对提交者信息做同样的处理。

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

git config user.email my_other_email@example.com 
git commit --amend

正如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

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

签出远程分支“master”选择“local_master_user_x”包含更改的项目/文件夹/文件右键单击-替换为-分支-“local_master_user_x”再次提交这些更改,这次是以正确的用户身份提交到本地分支“master”中推到远程“主机”

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

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

使用Git 1.7.5.4版进行测试。

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

您还可以执行以下操作:

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