如何编辑 git 的历史记录以更正不正确的电子邮件地址/名称

Cha*_*ens 78 git

当我开始使用 git 时,我只是做了 agit init并开始调用addcommit。现在我开始注意了,我可以看到我的提交显示为cowens@localmachine,而不是我想要的地址。看起来好像设置GIT_AUTHOR_EMAIL并且GIT_COMMITTER_EMAIL会做我想做的事,但我仍然有那些带有错误电子邮件地址/名称的旧提交。如何更正旧的提交?

小智 84

您可以通过一次调用 git filter-branch 返回并修复所有提交。这与 rebase 具有相同的效果,但您只需要执行一个命令来修复所有历史记录,而不是单独修复每个提交。

您可以使用以下命令修复所有错误的电子邮件:

git filter-branch --env-filter '
    oldname="(old name)"
    oldemail="(old email)"
    newname="(new name)"
    newemail="(new email)"
    [ "$GIT_AUTHOR_EMAIL"="$oldemail" ] && GIT_AUTHOR_EMAIL="$newemail"
    [ "$GIT_COMMITTER_EMAIL"="$oldemail" ] && GIT_COMMITTER_EMAIL="$newemail"
    [ "$GIT_AUTHOR_NAME"="$oldname" ] && GIT_AUTHOR_NAME="$newname"
    [ "$GIT_COMMITTER_NAME"="$oldname" ] && GIT_COMMITTER_NAME="$newname"
    ' HEAD
Run Code Online (Sandbox Code Playgroud)

可从git docs获得更多信息

  • 好吧, git filter-branch --env-filter 'export GIT_AUTHOR_EMAIL="foo@example.com";GIT_AUTHOR_NAME="Foo"' 简单多了,谢谢。如果我可以更改它,这将是公认的答案(看起来服务器故障存在错误)。 (12认同)
  • 请注意,导出行的等号两侧不应有空格。即它们应该是这样的: export GIT_AUTHOR_EMAIL="(correct email)" ; (7认同)
  • @Deckard:将脚本保存到fixcommits.sh 等文本文件中,然后运行Git Bash 并运行脚本。我将脚本文件放在我的 repo 的根目录中,然后导航到 Git Bash 中的该文件夹,然后使用 ./fixcommits.sh 运行脚本 (2认同)
  • **附录 1** 这种命令格式对我不起作用,但如果/那么做了:`if [ "$GIT_AUTHOR_EMAIL" = "$oldemail" ]; 然后 GIT_AUTHOR_EMAIL="$newemail"; 菲` (2认同)

wu-*_*lee 28

Git 的 filter-branch 命令功能强大,但用于任何非平凡的事情是非常笨拙的,例如,如果您有多个作者需要更正。

这是我发现有用的替代方法,它使用 git-shortlog 联机帮助页中描述的 .mailmap 功能。这提供了一种作者映射机制,我们可以与 git log 的格式化工具一起使用。我们可以使用它来生成命令来选择和修改修改一个命名的提交序列。

例如,假设您要更正分支 $BRANCH 上的作者身份,从提交 $START 开始。

您需要在存储库的顶级目录中创建一个 .mailmap 文件,该文件将现有作者姓名映射到正确的姓名。您可以通过以下方式获取现有作者姓名的列表:

git shortlog -se
Run Code Online (Sandbox Code Playgroud)

你需要得到一个像这样的 .mailmap 文件(比如说):

You <you@somewhere.org>   cowens@localmachine
You <you@somewhere.org>   root@localmachine
Run Code Online (Sandbox Code Playgroud)

现在您可以使用 git log 的格式化功能来生成将 $BRANCH 重写为 $BRANCH2 的命令。

git checkout -b $BRANCH2 $START
git log --reverse --pretty=format:"cherry-pick %H; commit --amend --author='%aN <%aE>' -C %H" $START..$BRANCH | sh - 
Run Code Online (Sandbox Code Playgroud)

第一个命令从提交 $START 创建一个新的空分支。对于 $START 和 $BRANCH 结束之间的每次提交,第二个命令会挑选原始提交到当前分支 $BRANCH2 的末尾,并对其进行修改以正确设置作者。

这也普遍适用 - 把它放在你的 ~/.gitconfig 中:

[alias]
    # git reauthor $START..$END
    reauthor = !sh -c 'eval `git log --reverse --topo-order --pretty=format:\"git cherry-pick %H &&  git commit --amend -C %H --author=\\\"%aN <%aE>\\\" && \" $0 ` "echo success" '
Run Code Online (Sandbox Code Playgroud)

因此,当您需要更正作者时,现在您只需要生成一个 .mapfile 并执行以下操作:

git checkout -b $BRANCH2 $START
git reauthor $START..$BRANCH
Run Code Online (Sandbox Code Playgroud)

可以将原始分支 ref 重新分配给新的,并删除新的:

git checkout $BRANCH
git reset --hard $BRANCH2 # be careful with this command
git branch -d $BRANCH2
Run Code Online (Sandbox Code Playgroud)


Cha*_*ens 9

结合如何在 git 中的第一次提交时修复元信息的答案

### Fix the first commit ###    
# create a temporary tag for the root-most commit so we can reference it
git tag root `git rev-list HEAD | tail -1`
# check it out on its own temporary branch
git checkout -b new-root root
# amend the commit
git commit --amend --author "Foo foo@example.com"
# (or if you've set the proper git **config** values)
git commit --amend -C HEAD --reset-author
# now you've changed the commit message, so checkout the original branch again
git checkout @{-1}
# and rebase it onto your new root commit
git rebase --onto new-root root
### Fix the rest of the commits ###
git rebase -i root
# edit the file to read "edit <commit number> for each entry
# amend the commit
git commit --amend --author "Foo foo@example.com"
# (or if you've set the proper git **config** values)
git commit --amend -C HEAD --reset-author
# move to the next commit
git rebase --continue    
# continue running the last two commands until you see
# Successfully rebased and updated refs/heads/master.
### Clean up ###
# nuke the temporary branch we created
git branch -d new-root
# nuke the temporary tag we created
git tag -d root
Run Code Online (Sandbox Code Playgroud)


Che*_*ion 5

遵循 jedberg 的回答:您可以使用rebase -i并选择编辑有问题的提交。如果您使用git commit --amend --author <AUTHOR DETAILS>然后git rebase continue您可以通过并修复历史记录。