如何更新git提交作者,但修改时保留原始日期?

0dxa2lsx  于 2023-03-28  发布在  Git
关注(0)|答案(7)|浏览(240)

如果提交已经被提交并推送到仓库,如果想改变某个特定提交的作者,我可以这样做:

git commit --amend --reset-author

但是,这将更改原始提交日期。
我如何重置作者,但保留原始提交日期?

jslywgbw

jslywgbw1#

正如在其他一些答案中提到的,你可能会用途:

git commit --amend --reset-author --no-edit --date="<old-date>"

虽然这样做是可行的,但要把旧的日期放回原处需要大量的手工复制或输入。您可能希望通过只获取日志中最后一个条目的日期来自动获取日期:

git log -n 1 --format=%aD

将两者结合起来,使用一些shell魔法:

git commit --amend --reset-author --no-edit --date="$(git log -n 1 --format=%aD)"

这会自动将日志中最后一次提交的日期(也就是要修改的日期)设置为作者变更后的新提交的日期。
现在在大量的提交中更改作者,比如说因为你忘记在克隆的git repo中设置作者,交互式rebase是你的朋友:

git rebase -i <commit before wrong author and email>

然后将所有要调整的提交从pick更改为edit并保存文件。Git在每个要编辑的提交时停止,然后重新运行:

git commit --amend --reset-author --no-edit --date="$(git log -n 1 --format=%aD)" && \
    git rebase --continue

如果提交的次数比较少,你可以使用shell的arrow-up键重复这个命令,直到rebase完成。如果提交的次数比较多,输入arrow-up + return就太繁琐了,你可能需要创建一个小的shell脚本来重复上面的命令,直到rebase完成。

6tdlim6h

6tdlim6h2#

以下是如何使用rebase并保留 * 提交日期 * 和 * 作者日期:

git -c rebase.instructionFormat='%s%nexec GIT_COMMITTER_DATE="%cD" GIT_AUTHOR_DATE="%aD" git commit --amend --no-edit --reset-author' rebase -i <commit before wrong author and email>

这会把你带到你的git编辑器,你可以立即退出。如果它把你带到vim,你不知道该怎么做,输入:x,然后按回车键。
基于this Reddit thread

omqzjyyz

omqzjyyz3#

1.如果您正在执行rebase,则使用committer-date-is-author-date来保持日期与以前相同。

$ git commit --amend --committer-date-is-author-date

1.对于正常修改,复制original committer time并在使用--date标志修改时覆盖时间。

$ git log                     # copy the 'original-committer-time'
$ git commit --amend --reset-author --date="<original-committer-time>"

# e.g. git commit --amend --date="Fri Dec 23 18:53:11 2016 +0600"
iyzzxitl

iyzzxitl4#

嗯,最后,我找到了一个对我来说更简单的解决方案。我在包含git项目gitrewrite.sh的目录中创建了一个脚本,并修改了它的权限,以便它可以被执行:

$ chmod 700 gitrewrite.sh

然后我在shell脚本中放置:

#!/bin/sh

git filter-branch --env-filter '
NEW_NAME="MyName"
NEW_EMAIL="my-name@my-domain.com"
if [ "$GIT_COMMIT" = "afdkjh1231jkh123hk1j23" ] || [ "$GIT_COMMIT" = "43hkjwldfpkmsdposdfpsdifn" ]
then
    export GIT_COMMITTER_NAME="$NEW_NAME"
    export GIT_COMMITTER_EMAIL="$NEW_EMAIL"
    export GIT_AUTHOR_NAME="$NEW_NAME"
    export GIT_AUTHOR_EMAIL="$NEW_EMAIL"
fi
' --tag-name-filter cat -- --branches --tags

然后在terminal中运行脚本:

$ ./gitrewrite.sh

就这样。历史被改写。
将代码推送到存储库并添加force标志。
$ git push -f

重要提示:

对于其他阅读它的人,请记住,这将在git历史中创建新的引用,所以只能在私有仓库或尚未与其他人共享的仓库中执行此操作,因为它可能会导致引用损坏!
我的是私人回购,所以不用担心这一部分。如果它是公开的,那么也许使用其他建议的答案可能是一个更好的选择。

z2acfund

z2acfund5#

我们可以使用rebase autosquash来获得所需的行为:

git commit --fixup HEAD
git rebase --autosquash --committer-date-is-author-date HEAD~2

第一个命令在当前HEAD提交上创建一个新提交作为修正提交,修正提交意味着如果稍后使用--autosquash运行rebase,这个新提交将在旧提交上修正(与交互式rebase中的fixup相同)。第二个触发到HEAD上的rebase ~2 -表示HEAD的第二级父级,或原始HEAD的父级(在我们添加修正之前),所以这将触发一个只包含2个提交的变基。提交将被压缩在一起,并且添加-- committer-date-is-author-date意味着它将使用原始创作的提交的日期,而不是新提交真正创建的当前日期。
警告:如果提交已经被推送,如果你以任何方式重写推送的提交并强制推送,你将重写发布的历史,这通常被认为是一件非常糟糕的事情。如果没有其他人会在你的提交之上工作,这不是一个问题。

dauxcl2d

dauxcl2d6#

与@Aleks answer非常相似,我在git-tower上找到了最适合我的解决方案:
https://www.git-tower.com/learn/git/faq/change-author-name-email
您可以根据需要在以下脚本中设置WRONG_EMAILNEW_NAMENEW_EMAIL的值,并在您的git项目中运行它:

git filter-branch --env-filter '
WRONG_EMAIL="wrong@example.com"
NEW_NAME="New Name Value"
NEW_EMAIL="correct@example.com"

if [ "$GIT_COMMITTER_EMAIL" = "$WRONG_EMAIL" ]
then
    export GIT_COMMITTER_NAME="$NEW_NAME"
    export GIT_COMMITTER_EMAIL="$NEW_EMAIL"
fi
if [ "$GIT_AUTHOR_EMAIL" = "$WRONG_EMAIL" ]
then
    export GIT_AUTHOR_NAME="$NEW_NAME"
    export GIT_AUTHOR_EMAIL="$NEW_EMAIL"
fi
' --tag-name-filter cat -- --branches --tags

警告:这将改变作者和所有提交的电子邮件,其中WRONG_EMAIL显示为作者。
引用自https://git-scm.com/docs/git-filter-branch
git filter-branch有很多缺陷[...]。这些安全和性能问题无法向后兼容修复,因此不建议使用它。请使用替代的历史过滤工具,如git filter-repo。
如果你还是搞砸了,我希望你知道如何使用git reflog。正如@Aleks已经说过的:只在私人仓库里做这种事

1dkrff03

1dkrff037#

错误是在使用--author时使用--reset-author,这样就足够了:

git commit --amend --author 'My Name <email@example.com>'

从上面链接的选项的文档中可以看出,用于重置状态的选项:
这也会更新作者时间戳。
而仅仅覆盖作者的选项(可用的since forever,v1.5.0)没有提到任何这样的副作用。

相关问题