931

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

4

27 回答 27

968

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

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

PS--date=now将使用当前时间。

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

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

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

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

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

于 2011-02-16T13:50:43.163 回答
615

与设置和用于您要修复的提交的特定哈希的git filter-branchenv 过滤器一起使用。GIT_AUTHOR_DATEGIT_COMMITTER_DATE

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

例子:

如果你想改变commit的日期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'
于 2009-01-18T06:48:07.273 回答
440

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

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

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

于 2012-03-14T11:32:31.370 回答
277

做吧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
于 2015-07-21T13:25:36.290 回答
179

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

句法:

git redate -c 3

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

在此处输入图像描述

于 2016-10-17T20:24:34.147 回答
151

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

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

于 2017-02-02T08:50:58.393 回答
111
git commit --amend --date="now"
于 2018-04-07T15:16:42.437 回答
78

如何编辑多个提交日期

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

要更改最后 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"

更新(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
于 2019-10-30T09:32:21.547 回答
48

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

名称很重要:git-xxxPATH可以在任何地方输入:

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 ( ) 之前提交的作者/提交日期重置@~为同一小时,但 2 天前。


Ilya Semenov在评论中提到:

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

于 2014-07-05T09:29:07.470 回答
30

在阅读了所有答案后,我想出了一种更简洁、更方便的方式来一次编辑多个提交的日期,而无需交互地重新设置:

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

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

于 2020-09-25T16:21:34.750 回答
24

我创建了这个 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]

于 2017-11-24T22:20:39.317 回答
20

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

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

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

git push --force 

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

于 2016-04-25T00:34:39.213 回答
19

这是一个方便的别名,它将上次提交的提交时间和作者时间都更改为接受的时间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!"
于 2014-05-16T05:41:40.997 回答
19

以下 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"
}
于 2014-06-08T10:10:09.563 回答
19

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

GIT_COMMITTER_DATE="Wed Sep 23 9:40 2015 +0200" git commit --amend --date "Wed Sep 23 9:40 2015 +0200"
于 2015-09-23T07:41:28.397 回答
12

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

git commit --amend --date="12/31/2021 @ 14:00"
于 2021-01-01T12:59:37.250 回答
11

如果您想获得另一个提交的确切日期(假设您对一个提交进行了变基编辑并希望它具有原始预变基版本的日期):

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

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

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

于 2016-11-18T11:17:18.223 回答
11

如果提交尚未推送,那么我可以使用类似的东西:

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

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

于 2019-03-25T11:08:49.077 回答
8

如果要在标准 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 日期,从而节省大量时间来寻找正确的星期几,并减少对元素顺序的普遍挫败感。
  • 如果您希望 Author 和 Committer 日期相同,您只需引用之前设置的变量即可。

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

于 2016-02-05T08:58:48.893 回答
7

对于那些使用 Powershell 的人

git rebase DESIRED_REF^ -i

$commitDateString = "2020-01-22T22:22:22"
$env:GIT_COMMITTER_DATE = $commitDateString
git commit --amend --date $commitDateString
$env:GIT_COMMITTER_DATE = ""

git rebase --continue

归功于https://mnaoumov.wordpress.com/2012/09/23/git-change-date-of-commit/

于 2020-01-23T23:31:32.567 回答
7

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

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. 在该提交(第一个)的行上替换picke(编辑)
  3. 退出编辑器(ESC 后跟:wq在 VIM 中)
  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/

于 2020-07-04T13:16:22.813 回答
4

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

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

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

于 2020-11-23T10:07:07.403 回答
2

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

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?决定……)现在我可以推动了!

大家,新年快乐

于 2020-12-31T14:45:29.183 回答
1

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

#!/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
于 2017-09-14T10:24:20.523 回答
1

用于将最后 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 配置为签署提交)
于 2022-01-11T08:57:38.533 回答
0

TL;DR:匹配日期 + 重新创建 GPG 签名

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


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

...如果标签附有签名,则签名将被剥离。根据定义,保留签名是不可能的。...(来源:--tag-name-filter

但它也会破坏VerifiedGitHub 提交(以及其他 Git 托管位置,如果以相同方式实现)的漂亮徽章,所以这也将解决这个问题。部分。

Afaik 不可能通过git命令破坏(GPG)签名,它还包含提交日期而不是简单的签名日期,因此即使创作和提交的日期被移动,它'仍将是当前日期,例如:

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

因此,假设您有一个要从某个提交签名的存储库(我会选择根提交;如果其他人在该存储库上工作,则不推荐)。的文档git commit 说它也从环境变量中提取数据(如果存在),因此我们有一个地方可以输入输入。

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

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

所以我们有:

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

对于变基,让我们这样做:

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

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

# or "while :"
while true
do
    GIT_COMMITTER_DATE=$(git show --format=%ad --no-patch) \
        git commit --amend --gpg-sign --no-edit --allow-empty
    git rebase --continue
done

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

这将遍历每个edit带有 -marked 的提交,设置提交者的日期以匹配作者的日期,保留任何空提交,不会触及整个补丁主体,并将添加带有命令执行日期的签名。

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

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

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

具有真实历史树的示例。GitHub 似乎并不关心签名的日期(任何地方都没有参考),但它仍然会出现在git log.

于 2021-07-25T21:08:01.693 回答
0

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

但是,我的脚本只进行了最少的修改,并且花费了更少的时间来重写(如果您需要更新)许多提交,因为它一次完成了所有提交

change_git_history

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

解释:

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

这是修改提交日期的那些

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

以下是修改提交消息的内容:

if [ true = false ]; # impossible
then
    : # pass
elif [ "$GIT_COMMIT" = "$com_hash" ];
then
    sed 's/.*/$com_msg_esc/g'" # replace content with new content
else
    cat - # returns previous content
fi;

我们使用

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

(文档在这里filter-branch man

于 2022-01-12T16:26:13.613 回答