如何更改一系列提交的作者?
当前回答
一个带过滤器的衬里:
您可以使用gitfilter repo的回调功能(推荐替换过滤器分支)来更改与所有提交相关的名称和电子邮件:
git filter-repo --name-callback 'return b"New Name"' --email-callback 'return b"newemail@gmail.com"'
这比使用过滤器分支的解决方案性能更高,可能更可靠。
请注意,上面的命令会更改所有提交的作者(和提交者),如果您想有效地“编辑”某个作者,并且只修改该特定作者的提交,请使用--commit回调选项,如下所示:
git filter-repo --commit-callback '
old_email = b"oldemail@gmail.com"
new_email = b"newemail@gmail.com"
new_name = b"New Author"
if commit.author_email == old_email:
commit.author_email = new_email
commit.author_name = new_name
if commit.committer_email == old_email:
commit.committer_email = new_email
commit.committer_name = new_name
'
(只需将上面命令中的old_email、new_email和new_name变量更改为正确的值。)
其他回答
这个答案使用gitfilter分支,文档现在给出了这个警告:gitfilter分支有太多的缺陷,可能会对预期的历史重写造成不明显的影响(而且由于它的性能非常糟糕,因此几乎没有时间调查这些问题)。这些安全和性能问题不能向后兼容地解决,因此不建议使用。请使用其他历史筛选工具,如git filter repo。如果您仍然需要使用git过滤器分支,请仔细阅读安全(和性能)以了解过滤器分支的地雷,然后尽可能小心地避免列出的危险。
更改作者(或提交人)需要重写所有历史。如果您对此感到满意,并认为这是值得的,那么您应该查看gitfilter分支。手册页面包括几个示例,可帮助您入门。还要注意,您可以使用环境变量来更改作者、提交人、日期等的名称——请参阅git手册页面的“环境变量”部分。
具体来说,您可以使用以下命令修复所有分支和标记的所有错误作者名称和电子邮件(来源:GitHub帮助):
#!/bin/sh
git filter-branch --env-filter '
OLD_EMAIL="your-old-email@example.com"
CORRECT_NAME="Your Correct Name"
CORRECT_EMAIL="your-correct-email@example.com"
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
对于使用替代历史过滤工具gitfilter repo,您可以首先安装它并根据gitmailmap的格式构造gitmailmap。
Proper Name <proper@email.xx> Commit Name <commit@email.xx>
然后使用创建的mailmap运行过滤器repo:
git filter-repo --mailmap git-mailmap
对于windows下的用户,也可以使用git火箭过滤器工具。
根据文档:
更改提交作者姓名和电子邮件:
git-rocket-filter --branch TestBranch --commit-filter '
if (commit.AuthorName.Contains("Jim")) {
commit.AuthorName = "Paul";
commit.AuthorEmail = "paul@company.com";
}
如果您是该存储库的唯一用户,则可以使用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时可能会遇到一些粗糙的角落:它是新的,但尚未经过很好的测试。
最快、最简单的方法是使用gitrebase的--exec参数:
git rebase -i -p --exec 'git commit --amend --reset-author --no-edit'
这将创建如下所示的待办事项列表:
pick ef11092 Blah blah blah
exec git commit --amend --reset-author --no-edit
pick 52d6391 Blah bloh bloo
exec git commit --amend --reset-author --no-edit
pick 30ebbfe Blah bluh bleh
exec git commit --amend --reset-author --no-edit
...
这将自动运行,当您有数百次提交时,这将正常运行。
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之间的区别