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

How can one change the timestamp of an old commit in Git?

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


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

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

然后继续交互式rebase。

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

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

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

一切都在Git Bash中测试过。


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

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

例:

如果你想更改commit 119f9ecf58069b265ab22f1f97d2b648faf932e0的日期,你可以这样做:

1
2
3
4
5
6
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'


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

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

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


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

1
git rebase -i <ref>

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

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

最后继续使用您的交互式rebase:

1
git rebase --continue


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

句法:

1
git redate -c 3

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

enter image description here


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

1
git log --format=fuller

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

1
git rebase -i HEAD~6

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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格式指定作者日期和提交者日期来修改每个提交:

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

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

然后转到下一个提交:

1
git rebase --continue

重复此过程,直到您修改所有提交。使用git status检查进度。


在theosp的答案的基础上,我写了一个名为git-cdc的脚本(用于更改日期提交),我在PATH中添加了该脚本。

名称很重要:PATHPATH的任何位置都允许您输入:

1
2
3
git xxx
# here
git cdc ...

即使在Windows上,该脚本仍然使用bash(因为Git将从其msys环境调用它)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/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"

有了它,你可以输入:

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

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

1
git cdc @~"2 days ago"

这会将HEAD(@~)之前提交的作者/提交日期重置为同一小时,但是会在2天前重置。

Ilya Semenov在评论中提到:

For OS X you may also install GNU coreutils (brew install coreutils), add it to PATH (PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH") and then use"2 days ago" syntax.


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

这会更改上次提交的日期(时间戳)

git commit --amend --date"Thu May 28 18:21:46 2015 +0530"


如果它是前一次提交。

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

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

1
git push --force

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


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

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

用法:git cd

例子:

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

编辑:
这是一个更自动化的版本,它检查索引是否干净(没有未提交的更改)并重用最后一次提交消息,否则失败(防呆):

1
2
3
4
5
[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!"


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

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

样品用法:

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

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

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


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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 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
GIT_COMMITTER_DATE="Wed Sep 23 9:40 2015 +0200" git commit --amend --date"Wed Sep 23 9:40 2015 +0200"

如果你想获得另一个提交的确切日期(比如你修改了一个提交并希望它具有原始pre-rebase版本的日期):

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

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

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


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

1
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日期,节省大量时间查找正确的星期几和一般的元素顺序挫折。
  • 如果您希望Author和Committer日期相同,则只需引用先前设置的变量即可。

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


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#!/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

日期将被更改:

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

如果尚未提交,那么我可以使用类似的东西:git commit --amend --date ="Wed Mar 25 10:05:44 2020 +0300"
之后,git bash打开编辑器,显示已经应用的日期,所以你需要通过在VI编辑器命令模式":wq"中键入来保存它,你可以推送它