如何修改Git中的多个提交以更改作者


179

我在Git中进行了一系列提交,现在我意识到我忘记正确设置用户名和用户电子邮件属性(新机器)了。我尚未将这些提交推送到我的存储库中,因此如何在我这样做之前更正这些提交(仅master分支上的3个最新提交)?

我一直在查看git resetgit commit -C <id> --reset-author,但我认为自己的方向不正确。


1
您可能想要更改email属性的另一个原因是此github错误:remote: error: GH007: Your push would publish a private email address....`![远程拒绝]管理员->管理员(由于电子邮件隐私限制,推送被拒绝)。
craq

Answers:


230

当您触手可及的分支过滤功能时,重新设置/修改似乎效率很低:

git filter-branch --env-filter 'if [ "$GIT_AUTHOR_EMAIL" = "incorrect@email" ]; then
     GIT_AUTHOR_EMAIL=correct@email;
     GIT_AUTHOR_NAME="Correct Name";
     GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL;
     GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME"; fi' -- --all

(为了清楚起见,将它们分成几行,但这不是必需的)

完成后,请务必检查结果,以确保您没有做任何不必要的更改!


介意再解释一下吗?不确定是哪个过滤器分支
max pleaner 2014年

1
@maxpleaner git filter-branch --help非常简单:)
alediaferia 2015年

2
另请参阅help.github.com/articles/changing-author-info,该文档还添加--tag-name-filter catfilter-branch以便将标签迁移到新历史记录。它还使用--branches --tags代替--all,它仅重写分支和标签的历史记录,并保留其他历史记录refs(尽管除非您正在使用,否则可能不会有太大的不同git-notes
Tobias Kienzler

12
为了在最后两次提交中执行此操作,我将其替换-- --allHEAD~1..HEAD
nmz787 '18

1
@ nmz787如果显示多少条日志git log HEAD~2..HEAD
乔纳

147

与exec结合使用时,交互式变基方法非常好。您可以针对特定提交或对rebase中的所有提交运行任何shell命令。

首先设置您的git author设置

git config --global user.name "John Doe"
git config --global user.email johndoe@example.com

然后在给定的SHA之后重置所有提交的提交者

git rebase -i YOUR_SHA -x "git commit --amend --reset-author -CHEAD"

这将弹出您的编辑器以确认更改。您需要做的就是保存并退出,它将通过每次提交并运行-x标志中指定的命令。

根据以下@Dave的评论,您还可以通过以下方式更改作者,同时保持原始时间戳:

git rebase -i YOUR_SHA -x "git commit --amend --author 'New Name <new_address@example.com>' -CHEAD"

3
感谢您向我介绍-x选项。太棒了!对于-i选项,我使用HEAD〜4在最近的4次提交中修复了我的电子邮件地址。像魅力一样运作。
布莱德·海因

2
这比filter-branch只想修复最后的提交要简单得多:)。但是请注意,这会更改提交的时间戳。
luator

24
要更改作者但保留原始时间戳,请使用git rebase -i YOUR_SHA -x "git commit --amend --author 'New Name <new_address@example.com>' -CHEAD"
Dave

2
@Connor git log也向我显示了旧的作者身份,但是git status正确地标识了新的提交,并且在强制推送之后它们符合我的意图。
Dan M.

6
要重新设置包括根目录在内的所有提交,请使用:git rebase -i --root …而不是传递SHA。
gfullam '19

80

要仅针对最后一次提交更改作者:

git commit --amend --author 'Author Name <author.name@mail.com>' --no-edit

假设您只想更改最近N次提交的作者:

git rebase -i HEAD~4 -x "git commit --amend --author 'Author Name <author.name@mail.com>' --no-edit"

笔记

  • --no-edit标志可以确保git commit --amend不要求额外的确认
  • 使用时git rebase -i,您可以手动选择更改作者的提交,

您编辑的文件将如下所示:

pick 897fe9e simplify code a little
pick abb60f9 add new feature
exec git commit --amend --author 'Author Name <author.name@mail.com>' --no-edit
pick dc18f70 bugfix

1
对于来自根的所有提交。git rebase -i --root UPTO_COMMIT_SHA -x“ git commit --amend --author'NEW_CHANGE'--no-edit”
Ashish Negi

1
我建议添加--rebase-merges(short -r)选项,以在分支包含某些合并的情况下保持分支的拓扑完整。
donquixote

3

github为此目的记录了这种方法。这些步骤是:

  1. 打开终端,并作出裸露的回购克隆
git clone --bare https://github.com/user/repo.git
cd repo
  1. 编辑下面的脚本(取代OLD_EMAILCORRECT_EMAILCORRECT_NAME
#!/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
  1. 将脚本复制/粘贴到您的终端中,然后按Enter键运行它。
  2. 推动您的更改,git push --force --tags origin 'refs/heads/*'您就完成了!

我在GitHub上遵循了您所引用的相同说明,现在GitHub看起来像。但是,我是Git newb,不确定在此之后如何同步本地存储库。当我拉动时,我得到另一个答案中提到的相同“拒绝合并无关历史”错误。我想我需要根据新的提交历史记录作为基础,但是我非常感谢更具体的步骤。

@enigment如果您对github上的存储库感到满意,则可以删除(或移动到其他位置)本地拥有的文件夹,并直接从github克隆
stevec

谢谢,我知道,但这似乎不是惯用的GitHub / Git方式。


0

如果您对下沉和修改感到不安全,则可以采用这种方法。同时,您还需要设置可能要执行的全局配置。

git reset HEAD~ (撤消上一次提交)

git config --global user.name "Your Name"

git config --global user.email you@example.com

git commit -m "message"

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.