如何更改一系列提交的作者?
当前回答
我想对@Rognon的回答进行修改。如果所选答案或其他答案不适用于您(在我的特定问题中就是这样),则此答案只是另一种选择:
目标:您将在所有历史记录中用正确的作者修复一个或多个作者,并且您将获得无重复的干净历史记录。此方法的工作原理是将“master”分支替换为“clean”分支(它不使用merge/rebase)
注意:任何使用“主”存储库的人都可能需要在推送之前再次签出(执行这些步骤后),因为合并可能会失败。
我们将使用一个名为“clean”的新分支来执行操作(假设您想修复“master”):
git checkout-b clean
(确保您处于“干净”分支:git分支)
修改以下脚本(替换电子邮件地址和名称)。请注意,此脚本需要两个错误的电子邮件/作者(例如),因此如果您只需要修复一个作者,则可以删除条件的第二部分或将其保持原样(因为它将被忽略,因为它不匹配)。
执行脚本。
#/bin/bash
git filter-branch --force --commit-filter '
if [ "$GIT_COMMITTER_EMAIL" = "wrong1@example.com" -o "$GIT_COMMITTER_EMAIL" = "wrong2@example.com" ];
then
export 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'被重写。如果报告“未更改”,则脚本中输入的电子邮件可能是错误的。
使用:git log确认历史已更正
如果您正在使用github/gitlab(建议=安全):
在remote中创建“clean”分支:
git push—设置上游原点清洁
将“clean”分支设置为默认分支删除“master”(在执行此操作之前,确保一切都符合预期)。基于“clean”分支创建一个新分支“master”。确认一切正常后,您可以立即删除“clean”分支(也可以重命名它)。
如果您没有使用github/gitlab,或者您更喜欢使用命令:
从本地删除主分支:
git分支-d主
重命名分支:
gitbranch-m清理主机
推它(确保你的“主人”没有受到保护)
git push—强制原始主机
其他回答
以上所有答案都改写了存储库的历史。只要要更改的名称未被多个作者使用,特别是如果存储库已共享且提交已过时,我更愿意使用.mailmap,记录在https://git-scm.com/docs/git-shortlog.它允许将不正确的名称/电子邮件映射到正确的名称,而无需修改回购历史记录。您可以使用以下行:
Proper Name <proper@email.xx> <root@localhost>
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
在重基完成后按^C#(循环将继续更新上次提交)
注意,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
您还可以执行以下操作:
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
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部分中此工具的限制。
推荐文章
- 为什么我需要显式地推一个新分支?
- 如何撤消最后的git添加?
- Rubymine:如何让Git忽略Rubymine创建的.idea文件
- Gitignore二进制文件,没有扩展名
- Git隐藏错误:Git隐藏弹出并最终与合并冲突
- 了解Git和GitHub的基础知识
- 没有。Git目录的Git克隆
- Git与Mercurial仓库的互操作性
- 忽略git中修改(但未提交)的文件?
- “git restore”命令是什么?“git restore”和“git reset”之间有什么区别?
- Git合并与强制覆盖
- Git拉另一个分支
- 在Bash命令提示符上添加git分支
- 如何更改Git日志日期格式
- git pull -rebase和git pull -ff-only之间的区别