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

如何修改现有的未推送提交?的答案描述了一种修改尚未向上推的先前提交消息的方法。新消息继承了原始提交的时间戳。这似乎是合乎逻辑的,但有没有办法重新设置时间?

501286 次浏览

git filter-branch与env过滤器一起使用,该过滤器为您要修复的提交的特定哈希设置GIT_AUTHOR_DATEGIT_COMMITTER_DATE

这将使该哈希和所有未来的哈希无效。

示例:

如果您想更改提交119f9ecf58069b265ab22f1f97d2b648faf932e0日期,您可以这样做:

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

您可以进行交互式rebase并为您要更改日期的提交选择edit。当rebase过程停止修改您输入的提交时,例如:

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

P. S.--date=now将使用当前时间。

之后,您继续您的交互式rebase。

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

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

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

一切都在Git Bash中测试。

在一个命令中处理所有这些建议的更好方法是

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

这会将最后一次提交的提交和作者日期设置为“现在”。

这是一个方便的别名,将最后一次提交的提交和作者时间更改为date --date接受的时间:

[alias]cd = "!d=\"$(date -d \"$1\")\" && shift && GIT_COMMITTER_DATE=\"$d\" \git commit --amend --date \"$d\""

用法:git cd <date_arg>

示例:

git cd now  # update the last commit time to current timegit cd '1 hour ago'  # set time to 1 hour ago

编辑:这是一个更加自动化的版本,它检查索引是否干净(没有未提交的更改)并重用最后一次提交消息,或者以其他方式失败(防傻瓜):

[alias]cd = "!d=\"$(date -d \"$1\")\" && shift && \git diff-index --cached --quiet HEAD --ignore-submodules -- && \GIT_COMMITTER_DATE=\"$d\" git commit --amend -C HEAD --date \"$d\"" \|| echo >&2 "error: date change failed: index not clean!"

以下bash函数将更改当前分支上任何提交的时间。

如果您已经推送了提交或在另一个分支中使用了提交,请注意不要使用。

# rewrite_commit_date(commit, date_timestamp)## !! Commit has to be on the current branch, and only on the current branch !!## Usage example:## 1. Set commit 0c935403 date to now:##   rewrite_commit_date 0c935403## 2. Set commit 0c935403 date to 1402221655:##   rewrite_commit_date 0c935403 1402221655#rewrite_commit_date () {local commit="$1" date_timestamp="$2"local date temp_branch="temp-rebasing-branch"local current_branch="$(git rev-parse --abbrev-ref HEAD)"
if [[ -z "$date_timestamp" ]]; thendate="$(date -R)"elsedate="$(date -R --date "@$date_timestamp")"fi
git checkout -b "$temp_branch" "$commit"GIT_COMMITTER_DATE="$date" git commit --amend --date "$date"git checkout "$current_branch"git rebase "$commit" --onto "$temp_branch"git branch -d "$temp_branch"}

theosp回答的基础上,我编写了一个名为git-cdc(用于更改日期提交)的脚本,并将其放入我的PATH中。

名称很重要:git-xxx在您的PATH中的任何位置都允许您键入:

git xxx# heregit 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" ]]; thenexit 0fi
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(@~)之前提交的作者/提交日期重置为同一小时,但2天前。


伊利亚·塞梅诺夫提到在评论

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

只需执行git commit --amend --reset-author --no-edit。对于较旧的提交,您可以执行交互式rebase并为要修改日期的提交选择edit

git rebase -i <ref>

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

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

最后继续您的交互式rebase:

git rebase --continue

要同时更改作者日期和提交日期:

GIT_COMMITTER_DATE="Wed Sep 23 9:40 2015 +0200" git commit --amend --date "Wed Sep 23 9:40 2015 +0200"

如果要在标准Windows命令行中执行接受的答案(https://stackoverflow.com/a/454750/72809),则需要以下命令:

git filter-branch -f --env-filter "if [ $GIT_COMMIT = 578e6a450ff5318981367fe1f6f2390ce60ee045 ]; then export GIT_AUTHOR_DATE='2009-10-16T16:00+03:00'; export GIT_COMMITTER_DATE=$GIT_AUTHOR_DATE; fi"

备注:

  • 可以将命令拆分为多行(Windows支持使用carret符号^拆分行),但我没有成功。
  • 您可以编写ISO日期,从而节省大量时间来查找正确的星期几和对元素顺序的一般挫败感。
  • 如果您希望作者和提交日期相同,您可以引用先前设置的变量。

非常感谢博客作者:Colin Svingen。尽管他的代码对我不起作用,但它帮助我找到了正确的解决方案。

如果是前一次提交。

git rebase  -i HEAD~2git commit --amend --date=now

如果您已经推送到orgin并可以强制使用:

git push --force

如果你不能强制推送,如果推送,你不能改变提交!

我为此编写了一个脚本和Homebrew包。超级容易安装,您可以在GitHubPotatoLabs/git-redate页面上找到它。

语法:

git redate -c 3

你只需要运行git redate,你就可以编辑vim中最近5次提交的所有日期(还有一个-c选项用于你想返回多少次提交,它只是默认为5)。如果你有任何问题、意见或建议,请告诉我!

在此处输入图片描述

如果你想得到另一个提交的确切日期(假设你重新编辑了一个提交,并希望它具有原始预rebase版本的日期):

git commit --amend --date="$(git show -s --format=%ai a383243)"

这会将HEAD提交日期更正为完全提交日期a383243(如果有歧义,请包含更多数字)。它还会弹出一个编辑器窗口,以便您可以编辑提交消息。

这是您通常关心的作者日期-请参阅提交者日期的其他答案。

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

git log --format=fuller

如果你想更改最近6次提交的作者日期和提交者日期,你可以简单地使用交互式rebase:

git rebase -i HEAD~6

.

pick c95a4b7 Modification 1pick 1bc0b44 Modification 2pick de19ad3 Modification 3pick c110e7e Modification 4pick 342256c Modification 5pick 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检查您的进度。

已经有很多很好的答案,但是当我想在一天或一个月内更改多次提交的日期时,我找不到合适的答案。所以我为此创建了一个新的脚本并解释,希望它能帮助到某人:

#!/bin/bash
# change GIT_AUTHOR_DATE for commit at Thu Sep 14 13:39:41 2017 +0800# you can change the data_match to change all commits at any date, one day or one month# you can also do the same for GIT_COMMITTER_DATE
git filter-branch --force --env-filter '
date_match="^Thu, 14 Sep 2017 13+"
# GIT_AUTHOR_DATE will be @1505367581 +0800, Git internal formatauthor_data=$GIT_AUTHOR_DATE;author_data=${author_data#@}author_data=${author_data% +0800}                # author_data is 1505367581
oneday=$((24*60*60))
# author_data_str will be "Thu, 14 Sep 2017 13:39:41 +0800", RFC2822 formatauthor_data_str=`date -R -d @$author_data`
if [[ $author_data_str =~ $date_match ]];then# remove one day from author_datanew_data_sec=$(($author_data-$oneday))# change to git internal format based on new_data_secnew_data="@$new_data_sec +0800"export GIT_AUTHOR_DATE="$new_data"fi' --tag-name-filter cat -- --branches --tags

日期将被更改:

AuthorDate: Wed Sep 13 13:39:41 2017 +0800

我创建了这个npm包来更改旧提交的日期。

https://github.com/bitriddler/git-change-date

样品使用:

npm install -g git-change-datecd [your-directory]git-change-date

系统将提示您选择要修改的提交,然后输入新日期。

如果您想通过特定哈希更改提交,请运行此git-change-date --hash=[hash]

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

如果提交还没有推送,那么我可以使用这样的东西:

git commit --amend --date=" Wed Mar 25 10:05:44 2020 +0300"

之后,git bash打开具有已应用日期的编辑器,因此您只需在VI编辑器命令模式“: wq”中键入保存它,您就可以推送它

如何编辑多个提交日期

其他答案对于编辑多个提交日期不是很方便。几年后,我回到这个问题上来分享一种技术。

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

git rebase -i HEAD~4

编辑rebase如下,插入exec行以根据需要修改日期:

pick 4ca564e Do somethingexec git commit --amend --no-edit --date "1 Oct 2019 12:00:00 PDT"pick 1670583 Add another thingexec git commit --amend --no-edit --date "2 Oct 2019 12:00:00 PDT"pick b54021c Add some testsexec git commit --amend --no-edit --date "3 Oct 2019 12:00:00 PDT"pick e8f6653 Fix the broken thingexec git commit --amend --no-edit --date "4 Oct 2019 12:00:00 PDT"

更新(2021年9月):

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

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

然后你会看到类似

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

对于使用PowerShell的用户

git rebase DESIRED_REF^ -i
$commitDateString = "2020-01-22T22:22:22"$env:GIT_COMMITTER_DATE = $commitDateStringgit commit --amend --date $commitDateString$env:GIT_COMMITTER_DATE = ""
git rebase --continue

信用https://mnaoumov.wordpress.com/2012/09/23/git-change-date-of-commit/

将最后一次提交的日期设置为当前日期

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

将最后一次提交的日期设置为任意日期

GIT_COMMITTER_DATE="Mon 20 Aug 2018 20:19:19 BST" git commit --amend --no-edit --date "Mon 20 Aug 2018 20:19:19 BST"

将任意提交的日期设置为任意或当前日期

重新定位到上述提交之前并停止修改:

  1. git rebase <commit-hash>^ -i
  2. 在该提交(第一个)的行中将pick替换为e(编辑)
  3. 退出编辑器(ESC后跟VIM中的:wq
  4. 要么:
  • GIT_COMMITTER_DATE="$(date)" git commit --amend --no-edit --date "$(date)"
  • GIT_COMMITTER_DATE="Mon 20 Aug 2018 20:19:19 BST" git commit --amend --no-edit --date "Mon 20 Aug 2018 20:19:19 BST"

来源:https://codewithhugo.com/change-the-date-of-a-git-commit/

在阅读了所有答案之后,我想出了一种更简洁、更方便的方法来一次编辑多个提交的日期,而不需要交互式地重新建立基础:

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

它同时更改提交者和作者日期。

编辑最后3次提交的作者日期和提交日期:

git rebase -i HEAD~3 --committer-date-is-author-date --exec "git commit --amend --no-edit --date=now"

--exec命令附加在rebase中的每一行之后,您可以使用--date=...选择作者日期,提交者日期将与作者日期相同。

我想确保我在午夜准确地更新代码的版权注释,我不想冒cron出现微小延迟的风险。所以,我提交了代码,然后:

GIT_COMMITTER_DATE="Fri Jan 1 00:00:00 2021 +1000" git commit --amend --no-edit --date="Fri Jan 1 00:00:00 2021 +1000"

(或者甚至将UTC偏移设置为0?决定…)现在我可以推了!

新年快乐,大家🥳

修改最后一次提交的日期和时间的最简单方法

git commit --amend --date="12/31/2021 @ 14:00"

太长别读:匹配日期+重新创建GPG签名

(如果您知道剥离以保留原始签名的解决方法,请评论/编辑。)


我将讨论这个旧的线程,因为已经引入了签名提交的功能,所有这些git filter-branch和喜欢基本上剥离了文档中指定的签名:

…如果标签附有签名,签名将被剥离。根据定义,不可能保留签名。…(来源:过滤标签名称

但它也会破坏GitHub提交上漂亮的Verified徽章(如果以同样的方式实现,也会在其他Git托管场所),所以这也会解决这个问题。部分。

然而,不可能通过git命令修改(GPG)签名,因为它包含提交日期而不是签名以简单的方式的日期,因此即使移动了创作和提交的日期,它仍然是当前日期,例如:

commit <hash>gpg: Signature made Sun 25 Jul 2021 00:00:00 PM TZgpg:                using TYPE key KEYgpg: Good signature from "Signer <email@domain.tld>"Author:     Author <email@domain.tld>AuthorDate: Sat Jan 1 00:00:00 2000 +0000Commit:     Author <email@domain.tld>CommitDate: Sat Jan 1 00:00:00 2000 +0000

所以假设你有一个你想从某个提交中签名的存储库(我会选择根提交;如果其他人在存储库上工作,不推荐)。git commit的留档也从env vars中提取数据,如果存在,因此我们有一个地方可以放置输入。

要检索数据(可以使用git commit --date=...设置),我们可以查看git show --format=%ad,因此对于原始日期字符串,它将是:

git show --format=%ad --no-patch# Sat Jan 1 00:00:00 2000 +0000

所以我们有:

  • 起点
  • 每个提交的原始日期字符串
  • GIT_COMMITTER_DATE匹配日期(作者->提交者)

对于rebase,让我们这样做:

git rebase --root <branch-name> --keep-empty --interactive

这将用于分支<branch-name>的根提交,保留用git commit -m "empty" --allow-empty创建的任何空提交,并询问您要修改哪些提交。在那里,您将所需的提交从pick更改为edit(对于我的情况,将所有这些标记为edit),然后您将被放入一个分离的HEAD提交,从这里开始乐趣。

# or "while :"while truedoGIT_COMMITTER_DATE=$(git show --format=%ad --no-patch) \git commit --amend --gpg-sign --no-edit --allow-emptygit rebase --continuedone

(如果您没有指定user.signingkey,请使用--gpg-sign=<fingerprint>

这将遍历每个edit标记的提交,将提交者的日期设置为与作者的日期匹配,保留任何空提交,不会触及整个补丁正文,并将添加一个带有命令执行日期的签名。

一旦您看到fatal: No rebase in progress?,请按Ctrl-C停止循环并检查日志以确认日期匹配并且签名随处可见:

git log --pretty=fuller --show-signature

如果日志中一切正常,只需发出git push --force就完成了。现在您应该看到每个提交的Verified徽章。

一个真实的历史树. GitHub似乎并不关心签名的日期(任何地方都没有引用),但它仍然会出现在git log中。

将最后5次提交的日期更新为当前日期(此方法不允许更新初始提交):

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

对于所有提交之后提交95f5074…15074db2:

git rebase 95f5074…15074db2 --exec "git commit --amend --no-edit --date 'now'"

对于所有提交(包括初始提交):

git rebase --root --exec "git commit --amend --no-edit --date 'now'"

为交互模式添加-i

运行git log --format=fuller --show-signature以验证更改。

运行git push -f以更新远程存储库(⚠️危险区域)

有一些暗示。例如:

  • 提交ID将发生变化,因此您必须重新创建标签
  • 您将失去原始签名
  • 这将使用您的.gitconfig,这意味着您的密钥将用于签名提交(如果Git配置为签名提交)

我最近需要这个,并使我自己的脚本看起来很像git-redate

然而,我的脚本做了最小的修改,并且需要更少的时间来重写(如果您需要更新)许多提交,因为它一次完成所有提交

change_git_history

实际上这也允许更改提交消息

解释:

脚本连接了一堆bash if表达式,看起来像这样

这是修改提交日期的那些

if [ "$GIT_COMMIT" = "$com_hash" ]; # com is committhenexport GIT_AUTHOR_DATE="$com_date";export GIT_COMMITTER_DATE="$com_date";fi;

以下是修改提交消息的那些:

if [ true = false ]; # impossiblethen: # passelif [ "$GIT_COMMIT" = "$com_hash" ];thensed 's/.*/$com_msg_esc/g' # replace content with new contentelsecat - # returns previous contentfi;

我们使用推送所有更新

git filter-branch -f \--env-filter "$UPDATES" \--msg-filter "$MESSAGES" \-- "$REV"

(文档在这里过滤分支人

除了马特·蒙塔格的回答

如果您需要在rebase命令后将时间戳重置为当前时间

git rebase -i HEAD~2

您可以使用这些选项之一

pick 4ca564e Do somethingexec git commit --amend --no-edit --date=nowpick 1670583 Add another thingexec git commit --amend --no-edit --reset-author

两者都能奏效

2022年7月信息:

这一个与当前时间戳工作惊人:

git commit --amend --date=now --no-edit

这一个-任何日期格式:

git commit --amend --date="Mon Jul 25 10:37:36 2022 +0300" --no-edit
GIT_COMMITTER_DATE="Sun Nov 20 21:02 2022 +0530" git commit --amend --no-edit --date="Sun Nov 20 21:02 2022 +0530"git push -f

每次都奏效。