2584

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

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

但我正在考虑一些事情,我通过哈希或短哈希来识别提交。

4

22 回答 22

4344

交互式变基从历史中比您需要修改的提交更早的点开始 ( git rebase -i <earliercommit>)。在要重新设置的提交列表中,将文本从 更改为pickedit要修改的哈希的旁边。然后当 git 提示您更改提交时,使用以下命令:

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

例如,如果您的提交历史记录是A-B-C-D-E-Fas FHEAD并且您想更改 and 的作者CD那么您将...

  1. 指定git rebase -i B(这里是执行命令后您将看到的示例git rebase -i B
    • 如果您需要编辑A,请使用git rebase -i --root
  2. C将这两个和Dfrom的行更改pickedit
  3. 退出编辑器(对于 vim,这将是按 Esc 然后键入:wq)。
  4. 一旦变基开始,它将首先暂停在C
  5. 你会git commit --amend --author="Author Name <email@address.com>"
  6. 然后git rebase --continue
  7. 它会在D
  8. 然后你会git commit --amend --author="Author Name <email@address.com>"再次
  9. git rebase --continue
  10. 变基将完成。
  11. 用于使用git push -f更新的提交更新您的来源。
于 2010-06-15T04:31:46.400 回答
626

这个问题的公认答案是非常聪明地使用交互式变基,但不幸的是,如果我们试图更改作者的提交曾经位于随后被合并的分支上,它就会出现冲突。更一般地说,它不起作用在处理混乱的历史时。

由于我担心运行依赖于设置和取消设置环境变量来重写 git 历史的脚本,因此我正在根据这篇文章编写一个新答案,该答案与此答案相似但更完整。

与链接的答案不同,以下内容经过测试和工作。为清楚起见,假设这03f482d6是我们试图替换其作者的提交,并且42627abe是与新作者的提交。

  1. 签出我们正在尝试修改的提交。

     git checkout 03f482d6
    
  2. 让作者改变。

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

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

  1. 签出原始分支。

  2. 用本地的新提交替换旧提交。

     git replace 03f482d6 42627abe
    
  3. 根据替换重写所有未来的提交。

     git filter-branch -- --all
    
  4. 取下更换清洁剂。

     git replace -d 03f482d6
    
  5. 推送新的历史记录(仅在以下失败时使用 --force ,并且仅在使用git log和/或进行健全性检查后使用git diff)。

     git push --force-with-lease
    

而不是 4-5 你可以重新提交到新的提交:

git rebase -i 42627abe
于 2015-03-04T02:11:25.787 回答
310

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
    
  • 将更正后的历史推送到 GitHub:

    git push --force --tags origin 'refs/heads/*'
    

或者,如果您想推送选定的分支引用,请使用

```
git push --force --tags origin 'refs/heads/develop'
```
于 2015-06-09T16:02:45.953 回答
239
  • 将您的电子邮件重置为全局配置:

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

  • 现在重置提交的作者,无需编辑:

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

于 2017-04-05T12:44:43.013 回答
108

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

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

但是,如果您想更改多个提交的作者姓名,那就有点棘手了。您需要启动交互式 rebase,然后将提交标记为编辑,然后一一修改并完成。

开始变基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?消息时完成交互式变基。

于 2015-08-29T00:52:24.913 回答
66

您链接到的问题中的答案是很好的答案并且涵盖了您的情况(另一个问题更笼统,因为它涉及重写多个提交)。

作为尝试的借口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
于 2010-06-15T05:24:55.783 回答
50

之前提交:

在此处输入图像描述

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

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

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

git commit --amend --author=Eugen

在命令后提交:

在此处输入图像描述

例如更改所有从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
于 2018-06-30T12:16:07.640 回答
36

为了促进Eugen Konkov的回答,从根提交开始,使用--root标志。该--no-edit标志也很有帮助,因为使用它不会提示您每次提交都进入编辑器。

git rebase --root --exec "git commit --amend --author='name <email>' --no-edit"
于 2019-04-15T17:32:33.167 回答
34

找到一种可以快速更改用户并且对其他提交没有副作用的方法。

简单明了的方法:

git config user.name "New User"
git config user.email "newuser@gmail.com"

git log
git rebase -i 1f1357
# change the word 'pick' to 'edit', save and exit

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

git push --force-with-lease

详细操作

  • 显示提交日志并找出您要更改的提交之前的提交 ID:
git log
  • git rebase 从选择的提交 id 开始反向到最近:
git config user.name "New User"
git config user.email "newuser@gmail.com"
git rebase -i 1f1357

# change word pick to edit, save and exit
edit 809b8f7 change code order 
pick 9baaae5 add prometheus monitor kubernetes
edit 5d726c3 fix liquid escape issue   
edit 3a5f98f update tags
pick 816e21c add prometheus monitor kubernetes
  • rebase 将在下一个提交 ID 处停止,输出:
Stopped at 809b8f7...  change code order 
You can amend the commit now, with
  git commit --amend 

Once you are satisfied with your changes, run

  git rebase --continue
  • 确认并继续你的变基,直到它成功refs/heads/master.
# each continue will show you an amend message
# use git commit --amend --reset-author --no-edit to comfirm
# use git rebase --skip to skip
git commit --amend --reset-author --no-edit
git rebase --continue
git commit --amend --reset-author --no-edit
...
git rebase --continue
Successfully rebased and updated refs/heads/master.
  • git推送更新
git push --force-with-lease
于 2020-02-13T07:48:54.487 回答
19

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

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

请注意,在同一个分支上工作的人不多,因为这会破坏一致性。

于 2013-12-20T15:06:45.050 回答
18

这样做git rebase -i时,文档中有这个有趣的部分:

如果要将两个或多个提交合并为一个,请将"pick"第二个和后续提交的命令替换为"squash"or "fixup"。如果提交有不同的作者,折叠的提交将归属于第一个提交的作者。折叠提交的建议提交消息是第一个提交的提交消息和带有"squash"命令的提交消息的串联,但省略了带有命令的提交的提交消息"fixup"

  • 如果你有过A-B-C-D-E-F,
  • 并且您想更改提交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...

你可以删除前几行。

于 2013-08-28T01:03:14.967 回答
9

如果您要更改的提交不是最后一次提交,请按照以下步骤操作。如果您的提交在不同的分支中,则首先切换到该分支。

git checkout 分支名称

在要更改的提交之前查找提交并找到其哈希。然后发出 rebase 命令。

git rebase -i -p 提交哈希

然后编辑器将打开并为您要更改的提交输入“编辑”。让其他人使用默认的“选择”选项。一旦改变输入'esc'键和wq!退出。

然后发出带有修正选项的 git commit 命令。

git commit --amend --author="用户名电子邮件" --no-edit

然后发出以下命令。

git rebase -- 继续

在本地存储库中更新提交作者后,将更改推送到远程存储库。

于 2019-06-26T05:49:15.030 回答
7

提交推送后重命名作者姓名的步骤

  1. 首先键入“git log”以获取提交 ID 和更多详细信息
  2. git rebase i HEAD~10 (10 是显示在 rebase 上的总提交)

    If you Get anything like below

    fatal: It seems that there is already a rebase-merge directory, and I wonder if you are in the middle of another rebase. If that is the case, please try

    git rebase (--continue | --abort | --skip) If that is not the case, please rm -fr ".git/rebase-merge" and run me again. I am stopping in case you still have something valuable there.

  3. 然后根据需要输入“git rebase --continue”或“git rebase --abort”

    • 现在您将打开 rebase 窗口,单击键盘上的“i”键
    • 然后你会得到提交到 10 的列表 [因为我们已经通过了上面的 10 次提交] 如下所示

    pick 897fe9e simplify code a little

    pick abb60f9 add new feature

    pick dc18f70 bugfix

  4. 现在您需要在要编辑的提交下方添加以下命令,如下所示

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

    1. 就是这样,现在只需按 ESC, :wq 就可以了

    2. 然后 git push origin HEAD:BRANCH NAME -f [请注意 -f 强制推送]

    喜欢 git push -fgit push origin HEAD: dev -f

于 2019-08-20T12:37:08.387 回答
7

可选:如果您不想将本地更改发送到远程,请确保存储本地更改。

$ git status
$ git stash

更新最后一次提交的作者。

$ git log   // Old author in local and remote
$ git commit --amend --author="Author Name <email@address.com>"
$ git log   // New Author in local
$ git push origin <branch> --force-with-lease 
$ git log   // New Author in remote

然后,如果您使用git stashthen 恢复您的暂存更改

$ git stash pop
$ git status

然后,您应该为当前项目的下一次提交更新配置。

$ git config user.name "Author Name"
$ git config user.email "<email@address.com>"

并检查或编辑它git config --edit


澄清:在极少数情况下,您可以使用reflog$ ggpush -f恢复提交。无论如何,使用你受到的保护甚至比你只使用--force-with-lease-f

总帐

于 2020-07-31T17:19:05.040 回答
5

您可以从 github 的官方页面使用这些命令

https://help.github.com/en/github/using-git/changeing-author-info

这是命令

#!/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

在这里,您可以将旧电子邮件更改为您的新用户名和电子邮件地址。

于 2020-05-13T02:17:14.770 回答
5

如果您的机器上缺少设置,例如,在格式化之后,或者在没有设置(正确)这些命令的情况下没有正确配置 Git 时,可能会发生这种情况。

git config user.name "Author Name"
git config user.email "<email@address.com>"

为什么不按照Atlassian 的这篇文章让您的生活更简单呢?

  1. git commit --amend --author="Author Name <email@address.com>"
  2. 取消保护您的分支,如果它受到保护。在这个例子中,它是master; 因此,它将受到源代码存储库的保护
  3. git push origin master --force

这是最后一次提交的最简单场景。要获取任何“随机”提交,您需要:

  1. git rebase -i <Earlier Commit>.
  2. 更改您感兴趣的pick提交edit
  3. git commit --amend --author="Author Name <email@address.com>"
  4. 如果您的分支受到保护,请取消保护它。在这个例子中,它是master; 因此,它将受到源代码存储库的保护
  5. git push origin master --force

在推动之前,您始终可以git log在两者之间确定自己的位置。

于 2021-03-25T18:48:30.750 回答
4

对于这个问题还有一种懒惰的方法,特别是如果您有多个要更改的提交。就我而言,我有一个新分支,其中有几个提交错误的作者,所以对我有什么帮助:

转到您的原始分支:

git checkout develop

从中创建新分支:

git checkout -b myFeature develop 

在没有提交信息的情况下将其合并为一个提交:

git merge --no-commit --squash branchWrongAuthor

您可能还想进行更改:

git stage .

更改作者的姓名并提交更改:

git commit --amend --author "New Author Name <New Author Email>" -m "new feature added"

就是这样,您可以推动更改。

git push

之后,您可以删除作者错误的分支。

于 2019-05-17T08:43:19.573 回答
4

对于合并提交消息,我发现我无法使用 修改它rebase,至少在 gitlab 上是这样。它将合并显示为提交,但我无法基于该#sha。我发现这篇文章很有帮助。

git checkout <sha of merge>
git commit --amend # edit message
git rebase HEAD previous_branch

这三行代码完成了更改合并提交消息的工作(如作者)。

于 2019-10-01T22:33:12.593 回答
4

解决方案

  1. 安装(Git 项目推荐overgit filter-repo filter-repofilter-branch

    $ PACKAGE_TOOL install git-filter-repo
    
  2. .mailmap在 git 存储库的根目录中创建一个文件,其中包含

    New Name <new@ema.il> <old@ema.il>
    
  3. git filter-repo --use-mailmap


更多细节

  • git-filter-repo在他们的文档中将此列为示例
  • 不要像上面的示例那样根据电子邮件过滤器替换名称和电子邮件,而是查看git mailmap 文档中的其他示例
  • 您可以通过使用参数.mailmap调用来指定您自己的文件,而不是使用默认文件。git filter-repo--mailmap <filename>
  • git-filter-repo 在项目的 README.md中可以找到更多关于如何进一步过滤分支/标签/任何内容的示例。
于 2021-01-12T14:17:54.237 回答
3

在全球范围内更改您的提交者姓名和电子邮件:

$ git config --global user.name "John Doe"
$ git config --global user.email "john@doe.org"

更改每个存储库的提交者姓名和电子邮件:

$ git config user.name "John Doe"
$ git config user.email "john@doe.org"

为下一次提交更改作者信息:

$ git commit --author="John Doe <john@doe.org>"

提示:对于其他情况并阅读更多信息,请阅读帖子参考

于 2020-01-22T11:08:53.103 回答
2

如果您需要更改的是最后一次提交的作者并且没有其他人正在使用您的存储库,您可以撤消您的最后一次提交:

git push -f origin last_commit_hash:branch_name 

更改提交的作者姓名:

git commit --amend --author "type new author here"

退出打开的编辑器并再次推送您的代码:

git push
于 2019-03-26T17:34:34.560 回答
2

有一个适用于投票最多的问题的捷径:使用exec而不是edit

exec允许在指定的提交上运行命令。
使用它可以避免使用edit、退出到终端并git为每个 git 提交运行命令。
如果您必须更改历史记录中的多个提交,这将特别有用。

步骤是:

  1. 对较早的提交执行变基 ( git rebase -i <earliercommit>)
  2. 在打开的编辑器中,在您要编辑和添加的每个提交行之后添加一行exec git commit --amend --author="Author Name <email@address.com>" --no-edit(或者--reset-author如果您想重置为 git config 中设置的值,请​​使用)
  3. 保存并退出 - 这将为每个提交运行指定的命令,有效地改变作者

示例编辑器内容(更改前 2 个提交作者):

pick 1fc6c95 Patch A
exec git commit --amend --author="Author Name <email@address.com>" --no-edit
pick 6b2481b Patch B
exec git commit --amend --author="Author Name <email@address.com>" --no-edit
pick dd1475d something I want to split
pick c619268 A fix for Patch B
pick fa39187 something to add to patch A
pick 4ca2acc i cant' typ goods
pick 7b36971 something to move before patch B

# Rebase 41a72e6..7b36971 onto 41a72e6
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#  f, fixup = like "squash", but discard this commit's log message
#  x, exec = run command (the rest of the line) using shell
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#
于 2021-07-08T09:16:13.700 回答