如何在Git中更改旧提交的时间戳?

1111

如何修改已存在但未推送的提交信息?的答案描述了一种方式,可以修改尚未向上游推送的先前提交的消息。 新消息继承原始提交的时间戳。这似乎很合理,但是否有一种方法也可以重新设置时间?


140
git commit --amend --reset-author - Erick M. Sprengel
1
上面的评论^^ (@ErickM.Sprengel) 应该被接受为答案。易于运行,特别是最新提交。 - Wesley Gonçalves
@WesleyGonçalves 这只是一个部分答案。如果你不想将提交时间设置为现在怎么办?你的使用情况并不适用于每个人。 - undefined
30个回答

1199
您可以执行交互式变基,并选择要更改日期的提交记录的edit选项。当变基过程停止以修改提交记录时,您可以键入如下命令:
git commit --amend --date="Wed Feb 16 14:00 2011 +0100" --no-edit

顺带一提,--date=now 将使用当前时间。

之后,您可以继续进行交互式变基。

要更改提交日期而不是作者日期:

GIT_COMMITTER_DATE="Wed Feb 16 14:00 2011 +0100" git commit --amend --no-edit

上面的代码设置了一个环境变量GIT_COMMITTER_DATE,用于修改提交。

所有内容均在Git Bash中进行测试。


23
@nschum --date="" 和 --data "non-date-text" 都会产生相同的结果,即使用当前日期。需要说明的是,--date参数和--data参数所提供的是非日期文本(non-date-text),而不是一个有效的日期格式。 - Paul Pladijs
16
在git版本1.7.7.1中使用--date="now"命令会报错:致命错误:日期格式无效:now。 - Aragorn
9
如果您想更改的提交日期是最近的提交,无需进行rebase操作,只需执行git commit --amend命令即可。请注意,此操作将覆盖最近的提交。 - Eponymous
7
尝试使用unset GIT_COMMITTER_DATE而不是export GIT_COMMITTER_DATE=""。 - Mark E. Haase
2
我正在使用 --no-edit 以便您可以在自动化脚本中使用!`+ var fixedDate = strftime(new Date(), "%c");
  • var result = shelljs.exec("git commit --amend --date="" + fixedDate + "" --no-edit");`
- Marcello DeSales
显示剩余10条评论

654

使用带有 env 过滤器的 git filter-branch 命令,为你想要修复的特定提交哈希设置 GIT_AUTHOR_DATEGIT_COMMITTER_DATE

这将使得该提交哈希及其后续所有哈希都无效。

示例:

如果您想要更改提交 119f9ecf58069b265ab22f1f97d2b648faf932e0日期,可以使用类似以下命令:

git filter-branch --env-filter \
    'if [ $GIT_COMMIT = 119f9ecf58069b265ab22f1f97d2b648faf932e0 ]
     then
         export GIT_AUTHOR_DATE="Fri Jan 2 21:38:53 2009 -0800"
         export GIT_COMMITTER_DATE="Sat May 19 01:01:01 2007 -0700"
     fi'

7
请参见 "DATE FORMATS" https://www.kernel.org/pub/software/scm/git/docs/git-commit.html。 - Dustin
11
那个人找到了正确的值,但仅仅设置这些变量似乎并没有影响旧提交的日期。 - IQAndreas
49
“这将使得之前的哈希值以及所有未来的哈希值都失效。” - EpicDavi
25
这意味着您将不得不强制推送到任何远程仓库,已拉取该提交或任何未来提交的人将不得不重置并拉取,或者从头开始删除和克隆。据我所知,没有任何方法可以避免这种情况。 - EriF89
8
作为给初学者的提示,短哈希在if语句中不起作用,请使用长SHA-1。 - 40detectives
显示剩余12条评论

456

处理所有建议的更好方法是使用一个命令

LC_ALL=C GIT_COMMITTER_DATE="$(date)" git commit --amend --no-edit --date "$(date)"

这将设置最新提交的提交时间和作者时间为“现在”。


23
这个功能非常适合在交互式变基期间编辑特定的提交。 - friederbluemle
18
Git 似乎不会根据本地语言环境识别日期格式,因此为了完全正确,您需要将其更改为以下内容:LANG= GIT_COMMITTER_DATE="\date`" git commit --amend --date "`date`"`。 - Michał Góral
17
你也可以只输入 --date "now"。Git >= 2 将会解释它。 - wisbucky
15
LC_ALL=C 是什么意思?它设置程序的本地化环境变量为 C,这将覆盖所有语言和区域设置并使用标准 C 语言环境。这在一些情况下可以确保程序的行为与预期一致,例如在处理文本时强制使用 ASCII 字符集。 - stwykd
4
@stwykd 这确保了 $(date) 使用一个 Git 能够理解的格式,通过临时覆盖系统语言环境。 - pxeger
显示剩余5条评论

346

只需执行git commit --amend --reset-author --no-edit即可。对于旧的提交,您可以执行交互式变基并选择edit来修改所需更改的提交日期。

git rebase -i <ref>

然后使用 --reset-author--no-edit 修正提交以将作者日期更改为当前日期:

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

最后,继续进行交互式变基:

git rebase --continue

8
使用--reset-author是个不错的选择,它在git 1.6.6中推出(参考https://gitlog.wordpress.com/2010/01/13/git-1-6-6/)。 - Tim Abell
2
这个技巧非常有效,可以让Github按正确的顺序显示重新基于PR的提交记录,因为它们是按时间戳排序的,如果没有这个技巧,时间戳可能全部相同。 - Nathan Long
10
请注意,使用--reset-author命令将会重置作者和作者日期为当前时间。 - wisbucky
2
这会同时改变“COMMITTER DATE”吗? - luochen1990
1
至少在git 2.39.0版本中,--reset-author命令也会重置CommitDate - Hart Simha
显示剩余3条评论

215

我为此编写了一个脚本和Homebrew包。 安装非常简单,您可以在GitHub的PotatoLabs/git-redate页面找到它。

语法:

git redate -c 3

只需运行git redate,你就能够在vim中编辑最近5个提交的所有日期(还有一个-c选项用于选择回溯多少次提交,默认为5)。如果您有任何问题、评论或建议,请告诉我!

输入图片描述


5
很棒的东西,尽管我不得不使用vim而不是nano。 - howdoyouturnthison
感谢@Edmund提供的优秀脚本。在运行了git redate -c之后,我无法在vi中看到要编辑的日期。我只看到%cI | XXXXXXXXXXXXXXXX | 初始提交。你能帮忙吗?谢谢。 - Kiem Nguyen
@KiemNguyen,请将Homebrew软件包更新至v1.0.2版本,我已经测试过了,它仍然可以正常工作。 - bigpotato
7
完全同意 Mina 和 @howdoyouturnthison 的观点,为什么不通过 EDITOR 环境变量使其与所有编辑器兼容呢?(另外我使用的是 Linux,而非 Mac...) - ympostor
3
谢谢@Edmund!以防万一,您的脚本处理默认值COMMITS时可能会出现问题。如果没有设置,以下代码将仅对最后一次提交进行过滤(我猜/发现)。"git filter-branch -f --env-filter "$ ENVFILTER "HEAD〜$ COMMITS..HEAD >/dev/null" - Grigory Entin
显示剩余11条评论

184

每个提交都与两个日期相关联,即提交者日期和作者日期。您可以使用以下命令查看这些日期:

git log --format=fuller

如果您想更改最近6次提交的作者日期和提交者日期,您可以使用交互式变基:

git rebase -i HEAD~6
pick c95a4b7 Modification 1
pick 1bc0b44 Modification 2
pick de19ad3 Modification 3
pick c110e7e Modification 4
pick 342256c Modification 5
pick 5108205 Modification 6

# Rebase eadedca..5108205 onto eadedca (6 commands)
#
# 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
# d, drop = remove commit

如果您想更改日期,对于所有提交,请将pick替换为edit(或只使用e),然后保存并退出编辑器。

现在,您可以通过指定作者日期和提交者日期以ISO-8601格式修订每个提交:

GIT_COMMITTER_DATE="2017-10-08T09:51:07" git commit --amend --date="2017-10-08T09:51:07"

第一个日期是提交日期,第二个日期是作者日期。

然后使用以下命令前往下一个提交:

git rebase --continue

重复这个过程直到您修改完所有提交。使用 git status 检查您的进度。


1
我按照这个操作,结果出现了“分离头”! - Simon H
12
这是最好的且最简单的答案。小提示:在git commit --amend --no-edit --date=2017-10-08T09:51:07中使用--no-edit可以保留旧的提交信息。 - Mariusz Pawelski
2
你可能还想根据这里的描述更新GIT_COMMITTER_DATE,以更改先前Git提交的时间戳:http://eddmann.com/posts/changing-the-timestamp-of-a-previous-git-commit/ - smihael
2
@smihael,感谢你提供的链接。我已经在我的答案中包含了你的建议。 - Ortomala Lokni
2
由于 git log --format=fuller 的出色答案以及能够在一个命令中更改两个日期的能力,这是一个很好的答案。 - John Leuenhagen
显示剩余3条评论

133
git commit --amend --date="now"

3
谢谢!很好用,但只能适用于最新的提交。 - banan3'14
这非常适合将多个提交压缩为一个提交时使用,这总是保留最后一个提交的日期,谢谢! - andrestascon

114

如何编辑多个提交日期

其他答案不太方便编辑多个提交日期。我在几年后回到这个问题上来分享一种技巧。

要更改最后4次提交的日期:

git rebase -i HEAD~4

根据需要修改以下变基,插入exec行以根据需要修改日期:

编辑重置变基如下,插入exec行以根据需要修改日期:

(Two possible translations depending on the context.)
pick 4ca564e Do something
exec git commit --amend --no-edit --date "1 Oct 2019 12:00:00 PDT"
pick 1670583 Add another thing
exec git commit --amend --no-edit --date "2 Oct 2019 12:00:00 PDT"
pick b54021c Add some tests
exec git commit --amend --no-edit --date "3 Oct 2019 12:00:00 PDT"
pick e8f6653 Fix the broken thing
exec git commit --amend --no-edit --date "4 Oct 2019 12:00:00 PDT"

更新(2021年9月):

如果您想在变基指令列表中看到原始提交日期(Git 2.6+):

git config --add rebase.instructionFormat "[%ai] %s"

然后你会看到类似于

pick 4f5a371f [2021-09-08 02:56:50 -0700] Add npm events
pick 67937227 [2021-09-09 03:05:42 -0700] Fixup

1
可以使用当前日期/时间作为参数吗? - accfews
2
关于“是否可以使用当前日期/时间作为参数”的问题: “现在”被视为有效日期,因此上面的exec行将变为exec git commit --amend --no-edit --date "now" - Andrew Richards
作为补充,我编写了一个 Bash 脚本,将这个答案(多次提交)与被接受的答案(过滤器)结合起来:https://gist.github.com/pixelbrackets/e2c2b451b77516e69377ecb4fd6f3a0d - pixelbrackets
对于当前的日期,您可以执行 exec git commit --amend --reset-author --no-edit - sziraqui

47

theosp答案基础上,我编写了一个名为git-cdc(表示更改日期提交)的脚本,并将其放置在PATH中。

名称很重要:PATH中出现git-xxx后,您就可以键入:

git xxx
# here
git cdc ... 

那个脚本是bash编写的,即使在Windows上也是如此(因为Git将从其msys环境中调用它)。

#!/bin/bash
# commit
# date YYYY-mm-dd HH:MM:SS

commit="$1" datecal="$2"
temp_branch="temp-rebasing-branch"
current_branch="$(git rev-parse --abbrev-ref HEAD)"

date_timestamp=$(date -d "$datecal" +%s)
date_r=$(date -R -d "$datecal")

if [[ -z "$commit" ]]; then
    exit 0
fi

git checkout -b "$temp_branch" "$commit"
GIT_COMMITTER_DATE="$date_timestamp" GIT_AUTHOR_DATE="$date_timestamp" git commit --amend --no-edit --date "$date_r"
git checkout "$current_branch"
git rebase  --autostash --committer-date-is-author-date "$commit" --onto "$temp_branch"
git branch -d "$temp_branch"

有了那个,你可以输入:

git cdc @~ "2014-07-04 20:32:45"

这将重置HEAD(@~)之前的提交的作者/提交日期为指定日期。

git cdc @~ "2 days ago"

这将把 HEAD 前面的提交(@~) 的作者/提交日期重置为相同的小时数,但是两天之前。


Ilya Semenov评论中提到:

 

对于 OS X,您也可以安装 GNU coreutils(brew install coreutils),将其添加到 PATH (PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH") 然后使用 "2 days ago" 语法。


1
对我而言,只有将日期和时间放在一个引号中才有效:git cdc @~ "2014-07-04 20:32:45",否则它将无法识别时间,并且获取到的时间将是00:00:00(成为第三个参数)。 - peschü
3
对于OS X,您也可以安装GNU coreutils(brew install coreutils),将其添加到PATH(PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH"),然后使用“2天前”的语法。 - Ilya Semenov
2
@IlyaSemenov 很有趣。我已经将您的评论包含在答案中,以增加其可见性。 - VonC
我正在尝试使用您的第一个示例,但我一直收到“fatal: invalid date format:”错误。Mac OS X期望什么日期格式? - user94547
@usbsnowcrash 不确定在Mac上是否适用。第二个例子“2天前”可以吗? - VonC
我安装了coreutils,第二个方法对我有效。 - user94547

46
阅读所有回答后,我想到了一种更简洁和方便的方法,可以同时编辑多个提交的日期,而无需交互式地重新生成基础分支:

在不需要交互式重置的情况下,批量修改多个提交记录的日期的更简洁、更方便的方法:

git rebase HEAD~4 --exec "git commit --amend --no-edit --date 'now'"

它会更改提交者和作者的日期。


2
我喜欢你的回答,我需要所有本地提交记录,因此我执行了以下操作:git rebase origin/main --exec "git commit --amend --reset-author --no-edit" - A1rPun
很棒的解决方案。但我遇到了一个奇怪的问题。当我更改所有日期并使用git push -f -u origin bugfix将其推送到远程分支并在Bitbucket页面上查看时,它仍然包含先前提交的日期。但是,这不仅限于此解决方案,其他解决方案也有相同的情况。看起来Git仍然在某个地方保留着以前的日期。 - ka3ak
1
@ka3ak 我看到一个提交有两个日期/时间戳,AuthorDateCommitDate,可以使用 git log --pretty=fuller 命令显示,如 此处 所述。我猜 Bitbucket 显示的是 CommitDate 而不是 AuthorDate。在这种情况下,我建议使用以下命令(其中 t 是您想要设置的日期):t='2017-09-01 12:34:56'; GIT_COMMITTER_DATE="$t" git commit --amend --no-edit --date="$t"。此命令将更改 AuthorDateCommitDate - Pere Joan Martorell
@PereJoanMartorell 我会尝试。但是在此期间,我使用了以下方法:当我处于bugfix分支时,执行了git checkout -b bugfix_copy; git reset bugfix; git rebase ...(更改提交日期); git push origin +bugfix_copy:bugfix。在最后一个命令之后,即使是Bitbucket的页面也显示每个提交的当前时间。我之所以使用这种方法,还因为我想保留分支bugfix,其提交日期不会改变。 - ka3ak
与答案所声称的相反,这并不会更改提交者和作者的日期。我想编辑一个更改以使其成为可能,但是“有太多待处理的编辑,请稍后再试。” 这里是一个修改后的解决方案,遵循相同的方法:t='2023-06-01T13:12:04'; git rebase HEAD~2 --exec "GIT_COMMITTER_DATE='$t' git commit --amend --no-edit --date '$t'"。将日期字符串替换为“now”或您想要使用的任何日期。 - Chrisuu

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