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


当前回答

如果是上一次提交。

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

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

git push --force 

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

其他回答

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

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

(如果你知道一个可以保留原始签名的方法,请评论/编辑。)


我将碰到这个旧线程,因为签名提交的特性已经引入,所有这些git过滤器分支和喜欢基本上剥离了文档中指定的签名:

... 如果标签附加了签名,则签名将被剥离。根据定义,不可能保存签名. ...(来源:——tag-name-filter)

但它也会破坏GitHub提交上漂亮的验证徽章(如果以同样的方式实现,在其他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

假设你有一个回购,你想从某个commit(我用根commit;如果其他人负责回购,则不建议使用)。git提交的文档说,如果存在,它也会从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来匹配日期(author -> committer)

对于重基,我们这样做:

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

这将用于一个分支<branch-name>的根提交,保留任何用git commit -m "empty"——allow-empty创建的空提交,并询问你要修改哪个提交。在这里,您可以将所需的提交从pick更改为edit(对于我的情况,将所有这些都标记为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

(如果您没有用户名。指定签名密钥,使用——gpg-sign=<指纹>)

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

一旦你看到致命:没有调整进度?按Ctrl-C停止循环,检查日志,确认日期匹配,签名无处不在:

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

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

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

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

这个名字很重要:git-xxx在你的PATH中允许你输入:

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天前"语法。

如果你想在标准的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支持用斜杠符号^拆分行),但我没有成功。 您可以编写ISO日期,从而节省大量查找合适的星期几的时间,避免在元素顺序方面遇到麻烦。 如果您希望Author和Committer日期相同,则只需引用前面设置的变量即可。

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

对于那些使用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/