如何更改单个提交的提交作者?

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

相关:如何更改多个提交的作者和提交者名称/电子邮件?

1403764 次浏览

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

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

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

  1. 指定git rebase -i B这是执行#0命令后您将看到的示例
    • 如果您需要编辑A,请使用git rebase -i --root
  2. CD的行从pick更改为edit
  3. 退出编辑器(对于vim,这将是按Esc,然后键入:wq)。
  4. 一旦rebase开始,它将首先暂停在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使用更新的提交更新您的源。

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

作为尝试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"; thenforce='-f'shiftfi
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"; thenif test -n "$TARG_EMAIL"; thenGIT_AUTHOR_EMAIL="$TARG_EMAIL"export GIT_AUTHOR_EMAILelseunset GIT_AUTHOR_EMAILfiif test -n "$TARG_NAME"; thenGIT_AUTHOR_NAME="$TARG_NAME"export GIT_AUTHOR_NAMEelseunset GIT_AUTHOR_NAMEfifi
'
git filter-branch $force --env-filter "$filt" -- $br

当做git rebase -i时,文档中有这样有趣的一点:

如果您想将两个或多个提交折叠成一个,请将第二次和后续提交的命令"pick"替换为"squash""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"
  • 开始rebase操作
    • git rebase -i B^
    • B^选择B的父节点。
  • 你会想把一个空的提交之前每个提交修改
  • 您将需要将pick更改为squash

git rebase -i B^将为您提供的示例:

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

将其更改为:

# change commit B's authorpick sha-commit-empty1 emptysquash sha-commit-B some message# leave commit C alonepick sha-commit-C some message# change commit D's authorpick sha-commit-empty2 emptysquash sha-commit-D some message# leave commit E-F alonepick sha-commit-E some messagepick 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...

你可以去掉前几行。

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

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

要小心,不要有很多人在同一个分支上工作,因为这会破坏一致性。

这个问题的接受的答案非常巧妙地使用了交互式rebase,但不幸的是,如果我们试图更改的提交的作者曾经在随后合并的分支上,它会出现冲突。更一般地说,在处理混乱的历史记录时,它不起作用。

由于我担心运行依赖于设置和取消设置环境变量来重写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

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" ]thenexport GIT_COMMITTER_NAME="$CORRECT_NAME"export GIT_COMMITTER_EMAIL="$CORRECT_EMAIL"fiif [ "$GIT_AUTHOR_EMAIL" = "$OLD_EMAIL" ]thenexport 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'

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

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

然后你会看到你的终端,就像什么都没发生一样。实际上你正处于交互式rebase的中间。现在是时候使用上面的命令修改提交的作者名了。它将再次打开编辑器。退出并继续使用git rebase --continue进行rebase。对要编辑的提交计数重复相同的操作。您可以确保在收到No rebase in progress?消息时交互式rebase完成。

如果你只是想更改最后一次提交的作者,你可以这样做:

  • 将您的电子邮件重置为全局配置:

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

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

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

提交之前:

在此处输入图片描述

要修复所有提交的作者,您可以应用@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

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

git push -f origin last_commit_hash:branch_name

更改提交的作者名:

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

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

git push

为了进一步回答尤金·康科夫,从根提交开始,使用--root标志。--no-edit标志也很有帮助,因为它不会提示您为每个提交进入编辑器。

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

这个问题还有一种懒惰的方法,特别是如果你有不止一个想要更改的提交。在我的例子中,我有一个新分支,其中有几个提交与错误的作者,所以什么帮助了我:

转到您的原始分支:

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

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

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

git签出branch_name

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

git rebase-i-p hash的定义

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

然后发出带有修改选项的git提交命令。

git提交--修改--作者="Username email"--不编辑

然后发出以下命令。

git rebase--继续

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

提交后重命名作者名的步骤

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

    If you Get anything like below

    致命:似乎已经有一个rebase合并目录,并且我想知道你是否在另一个基地的中间。如果那是案例,请尝试

    git rebase (--continue | --abort | --skip)如果不是这样,请rm-fr". git/rebase合并"再查一次我要停下来以防你还有什么发现有价值的。

  3. 然后根据您的需要键入“git rebase-继续”或“git rebase-中止”

    • 现在您的将重新定位窗口打开,从键盘单击“i”键
    • 然后你会得到10个提交的列表[因为我们已经通过了10个提交]像下面一样

    pick 897fe9e simplify code a little

    pick abb60f9 add new feature

    pick dc18f70 bugfix

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

    选择897fe9e稍微简化代码exec git提交--修改--作者'作者姓名'选择abb60f9添加新功能exec git提交--修改--作者'作者姓名'选择dc18f70错误修复

    1. 就是这样,现在只需按ESC: wq,您就一切就绪

    2. 然后git推送源HEAD:分支名称-f[请照顾-f强制推送]

    例如git push -fgit push origin HEAD: dev -f

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

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

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

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

$ 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>"

提示:对于其他情况和阅读更多信息,请阅读后参考

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

简单明了的方法:

git config user.name "New User"git config user.email "newuser@gmail.com"
git loggit rebase -i 1f1357# change the word 'pick' to 'edit', save and exit
git commit --amend --reset-author --no-editgit 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 exitedit 809b8f7 change code orderpick 9baaae5 add prometheus monitor kubernetesedit 5d726c3 fix liquid escape issueedit 3a5f98f update tagspick 816e21c add prometheus monitor kubernetes
  • rebase将在下一次提交id时停止,输出:
Stopped at 809b8f7...  change code orderYou can amend the commit now, withgit commit --amend
Once you are satisfied with your changes, run
git rebase --continue
  • 确认并继续您的rebase,直到它成功地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 skipgit commit --amend --reset-author --no-editgit rebase --continuegit commit --amend --reset-author --no-edit...git rebase --continueSuccessfully rebased and updated refs/heads/master.
  • git推送更新
git push --force-with-lease

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

https://help.github.com/en/github/using-git/changing-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" ]thenexport GIT_COMMITTER_NAME="$CORRECT_NAME"export GIT_COMMITTER_EMAIL="$CORRECT_EMAIL"fiif [ "$GIT_AUTHOR_EMAIL" = "$OLD_EMAIL" ]thenexport GIT_AUTHOR_NAME="$CORRECT_NAME"export GIT_AUTHOR_EMAIL="$CORRECT_EMAIL"fi' --tag-name-filter cat -- --branches --tags

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

可选:如果您不想将本地更改发送到远程,请确保隐藏它们。

$ 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 stash,则恢复您的分阶段更改

$ git stash pop$ git status

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

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

然后用git config --edit检查或编辑它


澄清:在使用$ ggpush -f丢失提交的极少数情况下,您可以使用重排恢复它们。无论如何,使用--force-with-lease比仅使用-f更能保护您

GL

解决方案

  1. 安装#0(Git project建议#1而不是#2)

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

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


更多详情

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

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

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

为什么不遵循本文由艾特莱森让你的生活更简单?

  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. 在您感兴趣的提交上更改edit上的pick
  3. git commit --amend --author="Author Name <email@address.com>"
  4. 如果您的分支受到保护,请取消保护。在本例中,它是master;因此,它将受到源代码存储库的保护
  5. git push origin master --force

你总是可以在中间git log,以确定你在推动之前的位置。

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

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

这些步骤是:

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

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

pick 1fc6c95 Patch Aexec git commit --amend --author="Author Name <email@address.com>" --no-editpick 6b2481b Patch Bexec git commit --amend --author="Author Name <email@address.com>" --no-editpick dd1475d something I want to splitpick c619268 A fix for Patch Bpick fa39187 something to add to patch Apick 4ca2acc i cant' typ goodspick 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.#

作为Eugen Konkov的回答的补充,可以保留提交/作者日期。要仅修改作者而不修改最后三次提交的日期,请使用

git rebase --onto HEAD~3 --exec 'GIT_COMMITTER_DATE="$(git log -n 1 --format=%aD)" git commit --amend --reset-author --no-edit --date="$(git log -n 1 --format=%aD)"' HEAD~3

然后用力推

git push --force-with-lease

使用git rebase -i首选答案是高效的,但正如另一个答案中突出显示的那样,当要编辑的提交周围有合并时,它会变得混乱。使用git replace是明智的,但git filter-branch重写了其他分支和标签的所有历史记录,这不是我们通常想要的。

我想分享一个替代第一个答案的方法,即使有合并也很容易。在我的例子中,当我使用git rebase -i <earlier-commit>时,我首先要解决一个冲突,然后再继续rebase。事实上,使用打破命令比编辑命令更容易。并直接基于我们目标的提交。

让我们举个例子,假设git log显示…

commit a12afg...commit dloe7a...commit gh7ag1...commit qp3zaa...

假设您想更新提交gh7ag1的作者、消息或提交签名。您可以继续git rebase -i gh7ag1。在编辑器中,您将看到:

pick dloe7apick a12afg

只需添加一个出路命令:

breakpick dloe7apick a12afg

保存(:wq与VI,Ctrl+O然后Ctrl+X与纳米)。现在,您在提交后立即返回。您可以运行git commit --amend来更新作者、消息或签名(例如git commit --amend -S --author="Your Name <your-email>")。使用git log --show-signature进行验证。如果正确,您可以继续使用git rebase --continue

您可以在rebase中拥有尽可能多的打破命令。如果有下一个中断,继续将移动到下一个中断,或者应用剩余的提交(前提是它们标记为pick)。

我的2019的评论转换成一个答案:

修复最后六次提交的创作

  1. 首先为当前Git仓库设置正确的作者

    git config --local user.name FirstName LastNamegit config --local user.email first.last@example.com
  2. 然后将修复应用于最后六个提交

    git rebase --onto HEAD~6 --exec "git commit --amend --reset-author --no-edit" HEAD~6
  3. 最后强制推送到远程Git仓库

    git push --force-with-lease