GIT:将提交日期更改为作者日期

88

我能否将提交日期更改为作者日期?

我修改了一些提交记录,现在它们的日期都相同。 我想将其设置回旧日期(或作者日期)。这可能吗?

我使用Sourcetree,所以我有git命令行,但我不是专家。我的外部存储库是bitbucket。


2
与 https://dev59.com/T3RB5IYBdhLWcg3w9b19 相关。 - Martin G
是的,但我实际上已经推送了新的日期。 - kevingoos
1
但是新的提交日期反映了现实。你为什么想隐藏真相? - CB Bailey
1
因为我正在使用gource来展示进度,并且我刚刚更改了作者。所以实际上这并不是对代码的修改。 - kevingoos
4个回答

132

简短回答:

git filter-branch --env-filter 'export GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"'

说明:

filter-branch 允许您重写 git 历史记录。它可以对每个提交应用转换或根据特定条件过滤提交。有关详细说明和用法说明,请参见 git filter-branch --help

--env-filter 允许您设置在创建新历史记录期间存在的环境变量。它会为每个提交单独进行评估。


9
这应该被接受为正解。不过,@torek的回答也值得了解。 - a paid nerd
4
稍微解释一下会更好。 - starikcetin
1
@S.TarıkÇetin 这个命令只是按照 kevingoos 的要求设置了 committer-date=author-date - anion
4
我们也可以在结尾处定义提交范围,如 git filter-branch -f --env-filter '...' 338f1ac1..HEAD - Orkhan Alikhanov
要在最新提交(HEAD)上执行此操作,请使用HEAD^..HEAD作为提交范围。另外,对于选项,有时可能需要添加-f/--force(例如,您仍然拥有上次运行的备份)。 - ADTC
这个帖子竟然有这么多赞,可它什么都没做! - undefined

91
自从 Git 1.6.3 版本以来,git rebase 命令支持使用 --committer-date-is-author-date 选项实现此功能。
git rebase --committer-date-is-author-date

翻译:
设置committer日期没有简单的方法(编辑:但请参见下面的“编辑2”)。由于--date可以让您在提交时指定每个作者,因此很容易调整author日期。

环境变量GIT_COMMITTER_DATE可用于在提交时强制使用不同的时间戳。然而,请注意,您需要为重播的每个提交都进行调整。生成的新提交将具有不同的SHA-1(因为您已经更改了它的某些位,即提交者日期字段),这意味着您必须重新做所有后代提交。

这就是git filter-branch所做的事情(重新创建一些、许多或所有提交,并沿途进行更改,保留从旧的SHA-1 ID到新的SHA-1 ID的映射,并调整即使是未经触及的提交副本的父级,以便“新”的新SHA-1 ID DAG以每种可能的方式与“旧”的DAG匹配,即除了SHA-1 ID和任何其他由您的筛选器进行的更改之外)。

换句话说,要做到这一点,您必须使用git filter-branch来重写历史记录,并伴随着所有这意味着的一切。[编辑:您可以直接在git rebase -i中完成此操作,例如通过使用--committer-date-is-author-date选项,但效果是相同的,但会更加方便。]

编辑2:正如eis在评论中指出的那样(已被删除),git rebase具有--committer-date-is-author-date选项用于此目的。它仍然执行相同的历史记录重写,但比使用原始的git filter-branch命令要方便得多。


6
很不幸,当与 --root 结合使用时,--committer-date-is-author-date 看起来相当有问题。 - user1338062
6
请注意,我们可以使用例如 git rebase --committer-date-is-author-date HEAD~3 的命令来仅将其应用于最近的三个提交记录。 - He Yifei 何一非
@HeYifei何一非 是的,但前提是这三个提交必须是普通的单父提交;要注意历史记录中的合并情况。HEAD~3 表示向后数三个第一父提交。 - torek
是的,但我在rebase -i的过程中放了一个break,所以我不能用现有的rebase再做一次rebase。在这种独特的情况下,filter-branch是唯一的方法。 - ADTC

8

使用filter-repo的一行命令:

您也可以像这样使用{{link1:filter-repo}}(建议替代filter-branch):

git filter-repo --commit-callback 'commit.committer_date = commit.author_date'

这比filter-branch的性能要高得多。


1
请注意,如果提交者时间戳不是单调递增的,则某些Git命令可能会混乱和失效。如果应用于使用git rebase重新排列了提交记录的历史记录,则可能会发生这种情况。 - j6t
@j6t 感谢您指出这一点;虽然这不仅适用于我的答案,也适用于被接受的答案。 - aradalvand
将作者的所有值复制到提交者:git filter-repo --commit-callback 'commit.committer_date = commit.author_date; commit.committer_name = commit.author_name; commit.committer_email = commit.author_email' - undefined

5

我希望借鉴 jsphpl的答案,因为我正在寻找一种方法来做到这一点,但是有两个区别:

  • 我只想更改当前分支中的提交
  • 我希望重新编写的提交被签名

首先,您需要知道您的分支中第一个提交的ID:

git log master..your-branch-name --pretty="%H" | tail -1

那个命令的输出应该会像这样:c04b195ca1ed4c8a18c6a98d67b8a764a3006afc 将该 ID 插入以下命令中:
git filter-branch -f \
--env-filter 'export GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"' \
--commit-filter 'git commit-tree -S "$@";' \
c04b195ca1ed4c8a18c6a98d67b8a764a3006afc^...your-branch-name

每个提交的提交日期和作者日期现在应该匹配。您可以通过运行以下命令轻松查看和比较提交日期值来进行双重检查:
git log --format="%H %cI %aI %s" master...your-branch-name

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接