我想更改历史记录中一项特定提交的作者。 这不是最后一次提交。
我知道这个问题- 如何在git中更改提交的作者?
但是我正在考虑某些事情,在这里我通过哈希或短哈希来标识提交。
#1楼
在执行git rebase -i
时,文档中有一个有趣的地方:
如果要将两个或多个提交折叠为一个,请用
"squash"
或"fixup"
替换命令"pick"
用于第二个及以后的提交。 如果提交具有不同的作者,则折叠的提交将归因于第一个提交的作者。 对于折叠式提交,建议的提交消息是第一次提交的提交消息与使用"squash"
命令的提交消息的串联,但是使用"fixup"
命令省略了提交的提交消息。
- 如果您有
ABCDEF
的历史, - 并且您想要更改提交
B
和D
(= 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
。
-
- 您将需要在每次提交修改之前放置一个空提交
- 您将需要更改
pick
以squash
。
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...
您可以删除前几行。
#2楼
如果您使用的是集中式存储库,那么Amber的答案还有一个额外的步骤:
git push -f
强制更新中央存储库。
注意在同一分支上工作的人很少,因为它可能破坏一致性。
#3楼
这个问题的公认答案是非常巧妙地使用交互式资源库,但是如果我们尝试更改其作者的提交曾经位于随后合并的分支中,则不幸地显示出冲突。处理混乱的历史时。
由于我对运行依赖于设置和取消设置环境变量来重写git历史记录的脚本感到不安,因此我根据此帖子写了一个新答案, 该答案与此答案类似,但更为完整。
与链接的答案不同,以下内容已经过测试和运行。 为了说明清楚起见,假设03f482d6
是我们要替换其作者的提交,并且42627abe
是与新作者进行的提交。
检出我们尝试修改的提交。
git checkout 03f482d6
更改作者。
git commit --amend --author "New Author Name <New Author Email>"
现在我们有一个新的提交,其哈希值假定为
42627abe
。签出原始分支。
在本地用新提交替换旧提交。
git replace 03f482d6 42627abe
根据替换内容重写所有将来的提交。
git filter-branch -- --all
删除替换件以保持清洁。
git replace -d 03f482d6
推送新历史记录(仅在以下操作失败时才使用--force,并且仅在使用
git log
和/或git diff
进行完好性检查之后使用)。git push --force-with-lease
您可以只使用新提交而不是4-6:
git rebase -i 42627abe
#4楼
交互式重新定位在历史记录中比您需要修改的提交更早的一点( git rebase -i <earliercommit>
)。 在要重新提交的提交列表中,将文本从pick
更改为您想要修改的哈希旁边的edit
。 然后,当git提示您更改提交时,请使用以下命令:
git commit --amend --author="Author Name <email@address.com>"
例如,如果您的提交历史记录是ABCDEF
且F
为HEAD
,并且您想更改C
和D
的作者,那么您将...
- 指定
git rebase -i B
( 这是执行git rebase -i B
命令后将看到的示例 )- 如果您需要编辑
A
,请使用git rebase -i --root
- 如果您需要编辑
- 将
C
和D
从pick
更改为edit
- 重新启动基准后,它将首先在
C
暂停 - 您将
git commit --amend --author="Author Name <email@address.com>"
- 然后
git rebase --continue
- 它会在
D
再次暂停 - 然后,您将再次
git commit --amend --author="Author Name <email@address.com>"
-
git rebase --continue
- 重新设置将完成。
- 使用
git push -f
使用更新的提交来更新源。
#5楼
您链接到的问题中的答案是不错的答案,可以解决您的情况(另一个问题更笼统,因为它涉及重写多个提交)。
作为尝试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