如何更改一个特定提交的提交作者?

我想更改历史记录中一项特定提交的作者。这不是最后一次提交。

我知道这个问题 - 如何在 git 中更改提交的作者?

但是我正在考虑某些事情,在这里我通过哈希或短哈希来标识提交。

答案

交互式重新定位在历史记录中比您需要修改的提交更早的一点( git rebase -i <earliercommit> )。在要重新提交的提交列表中,将文本从pick更改为您想要修改的哈希旁边的edit 。然后,当 git 提示您更改提交时,请使用以下命令:

git commit --amend --author="Author Name <email@address.com>"

例如,如果您的提交历史记录是ABCDEFFHEAD ,并且您想更改CD的作者,那么您将...

  1. 指定git rebase -i B这是执行git rebase -i B命令后将看到的示例
    • 如果您需要编辑A ,请使用git rebase -i --root
  2. CDpick更改为edit
  3. 重新启动基准后,它将首先在C暂停
  4. 您将git commit --amend --author="Author Name <email@address.com>"
  5. 然后git rebase --continue
  6. 它会在D再次暂停
  7. 然后,您将再次git commit --amend --author="Author Name <email@address.com>"
  8. git rebase --continue
  9. 重新设置将完成。
  10. 使用git push -f使用更新的提交来更新源。

这个问题的公认答案是非常巧妙地使用交互式资源库,但是如果我们尝试更改其作者的提交曾经位于随后合并的分支中,则不幸地显示出冲突。处理混乱的历史时。

由于我对运行依赖于设置和取消设置环境变量来重写 git 历史记录的脚本感到不安,因此我根据此帖子写了一个新答案, 该答案此答案类似,但更为完整。

与链接的答案不同,以下内容已经过测试和运行。为了说明清楚起见,假设03f482d6是我们要替换其作者的提交,并且42627abe是与新作者进行的提交。

  1. 检出我们尝试修改的提交。

    git checkout 03f482d6
  2. 更改作者。

    git commit --amend --author "New Author Name <New Author Email>"

    现在我们有一个新的提交,其哈希值假定为42627abe

  3. 签出原始分支。

  4. 在本地用新提交替换旧提交。

    git replace 03f482d6 42627abe
  5. 根据替换内容重写所有将来的提交。

    git filter-branch -- --all
  6. 删除替换件以保持清洁。

    git replace -d 03f482d6
  7. 推送新历史记录(仅在以下操作失败时才使用 --force,并且仅在使用git log和 / 或git diff进行完好性检查之后使用)。

    git push --force-with-lease

您可以只使用新提交而不是 4-6:

git rebase -i 42627abe

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
  • 将您的电子邮件全局重置为配置:

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

  • 现在,无需修改即可重置提交的作者:

    git commit --amend --reset-author --no-edit

您可以使用以下命令更改最后提交的作者。

git commit --amend --author="Author Name <email@address.com>"

但是,如果您要更改多个提交者姓名,则有些棘手。您需要启动一个交互式基础,然后将提交标记为编辑,然后将它们逐一修改并完成。

开始使用git rebase -i重新设git rebase -i 。它会向您显示这样的内容。

https://monosnap.com/file/G7sdn66k7JWpT91uiOUAQWMhPrMQVT.png

更改pick关键字以edit要更改作者姓名的提交。

https://monosnap.com/file/dsq0AfopQMVskBNknz6GZZwlWGVwWU.png

然后关闭编辑器。对于初学者,请按Escape然后输入:wq并按Enter

然后,您将看到终端没有任何反应。实际上,您处于交互式基础的中间。现在是时候使用上面的命令修改提交的作者姓名了。它将再次打开编辑器。退出并继续使用git rebase --continue 。对要编辑的提交计数重复相同的操作。您可以确保在获得 “ No rebase in progress?基” 时完成交互式变No rebase in progress?信息。

您链接到的问题中的答案是不错的答案,可以解决您的情况(另一个问题更笼统,因为它涉及重写多个提交)。

作为尝试git filter-branch的借口,我编写了一个脚本来重写给定提交的作者名和 / 或作者电子邮件:

#!/bin/sh

#
# Change the author name and/or email of a single commit.
#
# change-author [-f] commit-to-change [branch-to-rewrite [new-name [new-email]]]
#
#     If -f is supplied it is passed to "git filter-branch".
#
#     If <branch-to-rewrite> is not provided or is empty HEAD will be used.
#     Use "--all" or a space separated list (e.g. "master next") to rewrite
#     multiple branches.
#
#     If <new-name> (or <new-email>) is not provided or is empty, the normal
#     user.name (user.email) Git configuration value will be used.
#

force=''
if test "x$1" = "x-f"; then
    force='-f'
    shift
fi

die() {
    printf '%s\n' "$@"
    exit 128
}
targ="$(git rev-parse --verify "$1" 2>/dev/null)" || die "$1 is not a commit"
br="${2:-HEAD}"

TARG_COMMIT="$targ"
TARG_NAME="${3-}"
TARG_EMAIL="${4-}"
export TARG_COMMIT TARG_NAME TARG_EMAIL

filt='

    if test "$GIT_COMMIT" = "$TARG_COMMIT"; then
        if test -n "$TARG_EMAIL"; then
            GIT_AUTHOR_EMAIL="$TARG_EMAIL"
            export GIT_AUTHOR_EMAIL
        else
            unset GIT_AUTHOR_EMAIL
        fi
        if test -n "$TARG_NAME"; then
            GIT_AUTHOR_NAME="$TARG_NAME"
            export GIT_AUTHOR_NAME
        else
            unset GIT_AUTHOR_NAME
        fi
    fi

'

git filter-branch $force --env-filter "$filt" -- $br

提交之前:

在此处输入图片说明

要修复所有提交的作者,您可以从 @Amber 的答案中应用命令:

git commit --amend --author="Author Name <email@address.com>"

要重用您的姓名和电子邮件,您可以写:

git commit --amend --author=Eugen

在命令后提交:

在此处输入图片说明

例如,更改所有从4025621开始的4025621

在此处输入图片说明

您必须运行:

git rebase --onto 4025621 --exec "git commit --amend --author=Eugen" 4025621

注意:要包括一个包含空格(例如姓名和电子邮件地址)的作者,该作者必须用转义引号引起来。例如:

git rebase --onto 4025621 --exec "git commit --amend --author=\"Foo Bar <foo@bar.com>\"" 4025621

或将此别名添加到~/.gitconfig

[alias]
    reauthor = !bash -c 'git rebase --onto $1 --exec \"git commit --amend --author=$2\" $1' --

然后运行:

git reauthor 4025621 Eugen

如果您使用的是集中式存储库,那么Amber 的答案还有一个额外的步骤:

git push -f强制更新中央存储库。

注意在同一分支上工作的人很少,因为它可能破坏一致性。

在执行git rebase -i时,文档中有一个有趣的地方:

如果要将两个或多个提交折叠为一个,请用"squash""fixup"替换命令"pick"用于第二个及以后的提交。如果提交具有不同的作者,则折叠的提交将归因于第一个提交的作者。对于折叠式提交,建议的提交消息是第一次提交的提交消息与使用"squash"命令的提交消息的串联,但是使用"fixup"命令省略了提交的提交消息。

  • 如果您有ABCDEF的历史,
  • 并且您想要更改提交BD (= 2 个提交),

那么您可以执行以下操作:

  • git config user.name "Correct new name"
  • git config user.email "correct@new.email"
  • 创建空的提交(每个提交一个):
    • 您需要一条消息用于变基
    • git commit --allow-empty -m "empty"
  • 开始变基操作
    • git rebase -i B^
    • B^选择的父B
  • 您将需要每次提交修改之前放置一个空提交
  • 您将需要更改picksquash

git rebase -i B^将给您的示例:

pick sha-commit-B some message
pick sha-commit-C some message
pick sha-commit-D some message
pick sha-commit-E some message
pick sha-commit-F some message
# pick sha-commit-empty1 empty
# pick sha-commit-empty2 empty

更改为:

# change commit B's author
pick sha-commit-empty1 empty
squash sha-commit-B some message
# leave commit C alone
pick sha-commit-C some message
# change commit D's author
pick sha-commit-empty2 empty
squash sha-commit-D some message
# leave commit E-F alone
pick sha-commit-E some message
pick sha-commit-F some message

它将提示您编辑消息:

# This is a combination of 2 commits.
# The first commit's message is:

empty

# This is the 2nd commit message:

...some useful commit message there...

您可以删除前几行。

为了增强 Eugen Konkov 的响应能力,从根落实开始,请使用--root标志。 --no-edit标志也很有用

git rebase --root --exec "git commit --amend --author='name <email>' --no-edit"