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


Answers:


535

git filter-branch与一个env过滤器一起使用,该过滤器可设置要查找的提交的特定哈希值,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'


8
找到了正确的值,但是设置这些变量实际上似乎并没有影响旧提交的日期。
IQAndreas 2014年

36
“这将使该值和所有将来的哈希值无效”是什么意思?
EpicDavi 2014年

16
EpicDavi:这意味着您将不得不强制推送到任何远程存储库,并且任何已撤回提交或将来的任何提交的人都必须重设和拉动,或者从头开始删除和克隆。据我所知,没有任何方法可以解决这个问题。
EriF89 2014年

4
就像给初学者的注释一样,短散列在if语句中不起作用,请使用长SHA-1
40detectives

780

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

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

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

更新(响应studgeek的评论):更改提交日期而不是作者日期:

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

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

一切都在Git Bash中进行了测试。


22
@nschum --date =“”和--data“ non-date-text”的结果相同,以现在的日期为准。
Paul Pladijs 2011年

12
在git版本1.7.7.1上使用--date =“ now”给出致命提示:无效的日期格式:now
Aragorn

4
如果您要更改其日期的提交是最近的提交,则不必执行rebase,您只需执行git commit --amend
同义的2012年

7
尝试取消设置GIT_COMMITTER_DATE,而不是导出GIT_COMMITTER_DATE =“”。
Mark E. Haase 2012年

2
我正在使用--no-edit,以便您可以在自动化脚本中使用!+ var fixedDate = strftime(new Date(), "%c"); + var result = shelljs.exec("git commit --amend --date=\"" + fixedDate + "\" --no-edit");
Marcello de Sales

392

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

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

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


22
在交互式变基期间编辑特定提交非常有用。
friederbluemle 2013年

2
您也可以为此在外壳上添加别名
kaleissin 2014年

14
看来,Git是不是语言环境感知日期格式的,所以是完全正确的,你必须让这样的事情:LANG= GIT_COMMITTER_DATE="`date`" git commit --amend --date "`date`"
米哈尔斑羚

我在重新设置基础和压缩分支时会这样做,因此它将创建具有更新时间戳记的单个提交。
路加·埃里斯曼

12
你也可以做--date "now"。Git> = 2将解释这一点。
Wisbucky

189

做吧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

5
利用良好的通话--reset-author,这在Git的新的1.6.6(REF gitlog.wordpress.com/2010/01/13/git-1-6-6
蒂姆·阿贝尔

1
这样做很好使Github以正确的顺序显示重新建立的PR的提交,因为它们是按时间戳排序的,并且没有这种技巧,时间戳可能都相同。
内森·朗

4
注意--reset-author会将“作者”和“作者日期”重置为现在。
Wisbucky

这会同时更改“提交日期”吗?
luochen1990

134

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

句法:

git redate -c 3

您只需要运行git redate,就可以在vim中编辑最近的5次提交的所有日期(您还可以-c选择要返回的提交数量,默认为5)。如果您有任何问题,意见或建议,请告诉我!

在此处输入图片说明


2
很棒的东西,即使我不得不使用vim而不是nano
howdoyouturnthison

感谢@Edmund提供了出色的脚本。运行git redate -c后,我看不到在vi中进行编辑的日期。我只看到%cI | XXXXXXXXXXXXXXXX | 初始提交。能否请你帮忙?谢谢
基姆·阮

@KiemNguyen您可以尝试git redate(不使用-c)吗?
bigpotato

4
完全同意Mina和@howdoyouturnthison在这里,为什么不通过EDITOR环境变量使它与编辑器无关?(也是我使用的是Linux,而不是Mac ...)
ympostor

3
谢谢@埃德蒙!以防万一,您的脚本在处理COMMITS的默认值时有问题。如果未设置,则以下代码仅将过滤器应用于(我猜/找到)最后一次提交。“ git filter-branch -f --env-filter” $ ENVFILTER“ HEAD〜$ COMMITS..HEAD> / dev / null”
Grigory Entin 17-10-30

101

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

git log --format=fuller

如果要更改作者的日期和最近6次提交的提交者日期,则可以使用交互式rebase:

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

对于您要更改日期的所有提交,请替换pickedit(或仅替换为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
我遵循了这个规则,最终陷入了“悬而未决的脑袋”!
西蒙H

1
@Simon H我已经再次测试了我的答案,并且效果很好。您应该输入其他内容,或者您​​已经陷入了沉思。如果您想从一个超脱的头回来,请执行git checkout name-of-current-branch
Ortomala Lokni

3
这是最好,最简单的答案。小提示:使用--no-edit git commit --amend --no-edit --date=2017-10-08T09:51:07保留旧的提交信息。
Mariusz Pawelski '18

2
您可能还想GIT_COMMITTER_DATE 按此处所述进行更新eddmann.com/posts/…–
smihael

2
@smihael感谢您的链接。我已经在您的回答中包括了您的建议。
Ortomala Lokni,


44

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

名称很重要:git-xxxPATH可以在任何位置键入:

git xxx
# here
git cdc ... 

该脚本甚至在Windows上也处于bash状态(因为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(@~)之前的提交的作者/提交日期重置为同一小时,但为2天之前。


Ilya Semenov 在评论中提到:

对于OS X,您也可以安装GNU coreutilsbrew install coreutils),将其添加到PATHPATH="/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 2015年

1
@IlyaSemenov有趣。我已将您的评论包含在答案中,以提高知名度。
VonC

我正在尝试使用您的第一个示例,但我不断收到“致命:无效的日期格式:”。Mac OS X需要什么日期格式?
usbsnowcrash

在Mac上不确定@usbsnowcrash。第二个示例“ 2 days ago”有效吗?
VonC

25

如何编辑多个提交日期

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

要更改最后4次提交的日期,请执行以下操作:

git rebase -i HEAD~4

如下所示编辑基准,插入exec行以根据需要修改日期:

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"

很好地使用--amend/ --date选项。比使用环境变量的答案简单。已投票。
VonC

是否可以使用当前日期/时间作为参数?
accfews

GIT_AUTHOR_DATE仅更新。
布莱斯

回覆。“是否可以使用当前日期/时间作为参数?”:“现在”被理解为有效日期,因此上述exec行将变为exec git commit --amend --no-edit --date "now"
Andrew Richards

20

如果是先前的最后一次提交。

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

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

git push --force 

如果您不能强制执行推送,而如果已推送,则无法更改提交!。


18

这是一个方便的别名,它将上次提交的提交时间和作者时间都更改为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 time
git 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!"

17

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

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

用法示例:

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

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

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


我只是想说这很棒,而且做得很漂亮。谢谢,您为我节省了大量时间!
paranza

17

以下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" ]]; then
        date="$(date -R)"
    else
        date="$(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"
}

1
您那里有一个错误: if [[ -z "$commit" ]]->if [[ -z "$date_timestamp" ]]
blueFast

真好!我建议GIT_COMMITTER_DATE=在方法末尾进行设置,以防止任何进一步的手动提交保持指定的日期。
loopkin

@loopkin,仅针对“ git commit”命令设置了GIT_COMMITTER_DATE,因此以后无需清除它
nimrodm

@nimrodm,我刚刚再次测试过,您是正确的。感谢您指出了这一点。
loopkin

12

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

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

10

如果要获取另一个提交的确切日期(例如,您对一个提交进行了重新设置基准并希望其具有原始重新设置基准版本的日期):

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

这会将HEAD提交的日期更正为恰好为a383243的提交日期(如果存在歧义,则包括更多数字)。它还将弹出一个编辑器窗口,以便您可以编辑提交消息。

那是针对作者的日期,这通常是您要注意的-有关提交者日期,请参见其他答案。


7

如果要在标准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博客文章。即使他的代码对我不起作用,它也帮助我找到了正确的解决方案。


7

如果尚未提交,那么我可以使用类似的方法:

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

之后,git bash将使用已应用的日期打开编辑器,因此您只需通过在VI编辑器命令模式下输入“:wq”来保存它,即可将其推送


2
只需添加一个不错的答案即可:如果您不想编辑提交消息(如果您只想更改提交日期),请使用该--no-edit选项。
Antonio Vinicius Menezes Medei

另外,如果已经推送了提交,您仍然可以使用git push -f(强制更新)推送更改的提交。不过,这可能会有副作用。(特别是如果有很多人在本地存储库的
副本


2

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

#!/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 format 
author_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 format
author_data_str=`date -R -d @$author_data`      

if [[ $author_data_str =~ $date_match ]];
then
    # remove one day from author_data
    new_data_sec=$(($author_data-$oneday))
    # change to git internal format based on new_data_sec
    new_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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.