我如何在过去做一个Git提交?

unk*_*own 204 git version-control repository git-commit

我将所有内容转换为Git供我个人使用,我发现存储库中已有一些旧版本的文件.如何根据文件的"修改日期"以正确的顺序将其提交到历史记录,以便我有一个准确的文件历史记录?

我被告知这样的事情会起作用:

git filter-branch --env-filter="GIT_AUTHOR_DATE=... --index-filter "git commit path/to/file --date " --tag-name-filter cat -- --all  
Run Code Online (Sandbox Code Playgroud)

Chr*_*sen 185

你给出的建议是有缺陷的.无条件地在一个设置中设置GIT_AUTHOR_DATE --env-filter会重写每次提交的日期.此外,在内部使用git commit也很不寻常--index-filter.

你在这里处理多个独立的问题.

指定"现在"以外的日期

每个提交都有两个日期:作者日期和提交者日期.您可以通过环境变量GIT_AUTHOR_DATE和GIT_COMMITTER_DATE为写入新提交的任何命令提供值来覆盖每个值.请参阅git-commit(1)或以下内容中的"日期格式":

Git internal format = <unix timestamp> <time zone offset>, e.g.  1112926393 +0200
RFC 2822            = e.g. Thu, 07 Apr 2005 22:13:13 +0200
ISO 8601            = e.g. 2005-04-07T22:13:13
Run Code Online (Sandbox Code Playgroud)

在正常使用期间写入新提交的唯一命令是git commit.它还有一个--date选项,可让您直接指定作者日期.您的预期用法还包括git filter-branch --env-filter使用上面提到的环境变量(这些是"env"的一部分,之后选项被命名;请参阅git-filter-branch(1)中的"Options"和底层的"plumbing"命令git-commit -tree(1).

将文件插入单个参考历史记录中

如果您的存储库非常简单(即您只有一个分支,没有标记),那么您可以使用git rebase来完成工作.

在以下命令中,使用提交的对象名称(SHA-1哈希)而不是"A".运行git commit时,不要忘记使用"日期覆盖"方法之一.

---A---B---C---o---o---o   master

git checkout master
git checkout A~0
git add path/to/file
git commit --date='whenever'
git tag ,new-commit -m'delete me later'
git checkout -
git rebase --onto ,new-commit A
git tag -d ,new-commit

---A---N                      (was ",new-commit", but we delete the tag)
        \
         B'---C'---o---o---o   master
Run Code Online (Sandbox Code Playgroud)

如果要更新A以包含新文件(而不是创建添加它的新提交),则使用git commit --amend而不是git commit.结果如下所示:

---A'---B'---C'---o---o---o   master
Run Code Online (Sandbox Code Playgroud)

只要您可以将提交命名为新提交的父级,上述操作就会起作用.如果您确实希望通过新的根提交(无父母)添加新文件,那么您需要一些不同的东西:

B---C---o---o---o   master

git checkout master
git checkout --orphan new-root
git rm -rf .
git add path/to/file
GIT_AUTHOR_DATE='whenever' git commit
git checkout -
git rebase --root --onto new-root
git branch -d new-root

N                       (was new-root, but we deleted it)
 \
  B'---C'---o---o---o   master
Run Code Online (Sandbox Code Playgroud)

git checkout --orphan是相对较新的(Git 1.7.2),但还有其他方法可以做同样的事情,适用于旧版本的Git.

将文件插入多参考历史记录

如果您的存储库更复杂(即它有多个ref(分支,标签等)),那么您可能需要使用git filter-branch.在使用git filter-branch之前,您应该制作整个存储库的备份副本.您的整个工作树(包括.git目录)的简单tar存档就足够了.git filter-branch确实可以创建备份引用,但通过删除.git目录并从备份中恢复它,通常可以更轻松地从不太正确的过滤中恢复.

注意:下面的示例使用lower-level命令git update-index --add而不是git add.您可以使用git add,但首先需要将文件从某个外部位置复制到预期路径(--index-filter在临时GIT_WORK_TREE中运行其命令为空).

如果您希望将新文件添加到每个现有提交中,则可以执行以下操作:

new_file=$(git hash-object -w path/to/file)
git filter-branch \
  --index-filter \
    'git update-index --add --cacheinfo 100644 '"$new_file"' path/to/file' \
  --tag-name-filter cat \
  -- --all
git reset --hard
Run Code Online (Sandbox Code Playgroud)

我真的没有理由改变现有提交的日期--env-filter 'GIT_AUTHOR_DATE=…'.如果你确实使用它,你就可以使它成为条件,这样它就会重写每次提交的日期.

如果您希望新文件仅在某些现有提交("A")之后出现在提交中,则可以执行以下操作:

file_path=path/to/file
before_commit=$(git rev-parse --verify A)
file_blob=$(git hash-object -w "$file_path")
git filter-branch \
  --index-filter '

    if x=$(git rev-list -1 "$GIT_COMMIT" --not '"$before_commit"') &&
       test -n "$x"; then
         git update-index --add --cacheinfo 100644 '"$file_blob $file_path"'
    fi

  ' \
  --tag-name-filter cat \
  -- --all
git reset --hard
Run Code Online (Sandbox Code Playgroud)

如果您希望通过要插入历史记录中间的新提交添加文件,则需要在使用git filter-branch之前生成新提交并添加--parent-filtergit filter-branch:

file_path=path/to/file
before_commit=$(git rev-parse --verify A)

git checkout master
git checkout "$before_commit"
git add "$file_path"
git commit --date='whenever'
new_commit=$(git rev-parse --verify HEAD)
file_blob=$(git rev-parse --verify HEAD:"$file_path")
git checkout -

git filter-branch \
  --parent-filter "sed -e s/$before_commit/$new_commit/g" \
  --index-filter '

    if x=$(git rev-list -1 "$GIT_COMMIT" --not '"$new_commit"') &&
       test -n "$x"; then
         git update-index --add --cacheinfo 100644 '"$file_blob $file_path"'
    fi

  ' \
  --tag-name-filter cat \
  -- --all
git reset --hard
Run Code Online (Sandbox Code Playgroud)

你也可以安排到一个新的根首先添加的文件提交:创建新的根通过从"赵氏孤儿"的方法提交git的变基节(捕获它new_commit),使用无条件的--index-filter,和--parent-filter喜欢"sed -e \"s/^$/-p $new_commit/\"".


mip*_*adi 111

您可以照常创建提交,但在提交时,请设置环境变量GIT_AUTHOR_DATE并设置GIT_COMMITTER_DATE相应的日期时间.

当然,这将使得提交位于分支的最前端(即,在当前HEAD提交之前).如果你想在回购中再推回它,你必须有点花哨.假设你有这样的历史:

o--o--o--o--o
Run Code Online (Sandbox Code Playgroud)

并且您希望新的提交(标记为"X")显示为第二个:

o--X--o--o--o--o
Run Code Online (Sandbox Code Playgroud)

最简单的方法是从第一次提交分支,添加新的提交,然后在新的提交之上重新设置所有其他提交.像这样:

$ git checkout -b new_commit $desired_parent_of_new_commit
$ git add new_file
$ GIT_AUTHOR_DATE='your date' GIT_COMMITTER_DATE='your date' git commit -m 'new (old) files'
$ git checkout master
$ git rebase new_commit
$ git branch -d new_commit
Run Code Online (Sandbox Code Playgroud)

  • `GIT_AUTHOR_DATE='Fri Jul 26 19:32:10 2013-0400' GIT_COMMITTER_DATE='Fri Jul 26 19:32:10 2013-0400' git commit` (87认同)
  • 我总能找到这个好的答案,但后来不得不赶紧找到日期格式,所以这里是下次'Fri Jul 26 19:32:10 2013 -0400' (20认同)
  • 还有更多,例如相当助记的`2013-07-26T19:32:10`:https://www.kernel.org/pub/software/scm/git/docs/git-commit.html#_date_formats (13认同)
  • 由于日期需要重复,我发现创建另一个变量更容易:`THE_TIME='2019-03-30T8:20:00 -0500' GIT_AUTHOR_DATE=$THE_TIME GIT_COMMITTER_DATE=$THE_TIME git commit -m 'commit message here' ` (10认同)
  • 顺便说一下,'-0400'部分表示时区偏移.请注意正确选择它...因为如果没有,您的时间将根据它改变.例如,在我居住在芝加哥的情况下,我不得不选择'-0600'(北美CST).您可以在此处找到代码:http://www.timeanddate.com/time/zones/ (3认同)
  • 如果你想自动获取文件时间: 如果你想自动获取文件时间: `THE_TIME=$(stat -c %y myfile)` (2认同)
  • 由于包含时区,最好使用“git log”命令,然后复制日期字符串并修改它。 (2认同)

Hyd*_* B. 91

我知道这个问题已经很老了,但这才是真正适合我的:

git commit --date="10 day ago" -m "Your commit message" 
Run Code Online (Sandbox Code Playgroud)

  • 这非常有效.我很惊讶`--date`也支持人类可读的相对日期格式. (12认同)
  • 如果是最后一次提交或一系列提交,则添加 `git rebase --committer-date-is-author-date &lt;ref&gt;`,其中 `&lt;ref&gt;` 是最后一次提交/分支/标签/...你不想改变。它的作用正如罐头上所说的那样。买者自负:如果这不是您分支上的最后一次提交,显然不起作用。 (8认同)
  • 警告:`git --date`只会修改$ GIT_AUTHOR_DATE ...所以根据情况你会看到提交的当前日期($ GIT_COMMITTER_DATE) (5认同)
  • 标记@ GuidoU.Draheim所说的。您可以使用git show &lt;commit-hash&gt; --format = fuller检查提交的全部详细信息。在那里,您会看到`AuthorDate`是您指定的日期,但是`CommitDate`是提交的实际日期。 (2认同)

ski*_*age 33

在我的情况下,随着时间的推移,我已经保存了一堆myfile的版本,如myfile_bak,myfile_old,myfile_2010,backups/myfile等.我想使用修改日期将myfile的历史记录放在git中.所以将最旧的重命名为myfile, git add myfile然后git commit --date=(modification date from ls -l) myfile将下一个最旧的重命名为myfile,使用--date重命名另一个git,重复...

要稍微自动化,可以使用shell-foo来获取文件的修改时间.我开始使用ls -lcut,但stat(1)更直接

git commit --date="`stat -c %y myfile`" myfile

  • `git commit`选项`--date`只会修改`GIT_AUTHOR_DATE`,而不是'GIT_COMMITTER_DATE`.正如[Pro Git Book](http://progit.org/book/ch2-3.html)所解释的那样:_"作者是最初编写作品的人,而提交者是最后一次应用作品的人."_在日期的上下文中,`GIT_AUTHOR_DATE`是文件被更改的日期,而`GIT_COMMITTER_DATE`是它提交的日期.这里需要注意的是,默认情况下,`git log`将作者日期显示为"Date",但在给出`--since`选项时使用提交日期进行过滤. (13认同)
  • 好的。我当然有 _git 天_之前的文件,我想使用文件修改时间。但是,这不只是设置提交日期(不是作者日期?) (2认同)

mx0*_*mx0 25

要进行看起来像过去完成的提交,您必须同时设置GIT_AUTHOR_DATEGIT_COMMITTER_DATE

GIT_AUTHOR_DATE=$(date -d'...') GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE" git commit -m '...'
Run Code Online (Sandbox Code Playgroud)

wheredate -d'...'可以是确切日期 like2019-01-01 12:00:00或 relative like 5 months ago 24 days ago

要在 git log 中查看两个日期,请使用:

git log --pretty=fuller
Run Code Online (Sandbox Code Playgroud)

这也适用于合并提交:

GIT_AUTHOR_DATE=$(date -d'...') GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE" git merge <branchname> --no-ff
Run Code Online (Sandbox Code Playgroud)

  • 警告:这里的“date”命令以本地语言给出日期,而您的命令对于非英语用户给出错误。因此,无论谁想使用它,都应该在命令行中将语言设置为英语,例如 `LC_TIME=en_US.utf8` (2认同)

小智 21

这是一个古老的问题,但我最近偶然发现了它。

git commit --date='2021-01-01 12:12:00' -m "message"工作正常并在GitHub.

  • 它对我来说工作得很好,只需添加更多说明即可, git commit --date='年-月-日 时:分:秒' -m "message" (5认同)
  • 我使用自己的时区还是 UTC? (4认同)
  • @Rahul你可以用 `git log --pretty='%cn %cd - %an %ad' HEAD` 看到 GIT_COMMITTER_DATE 和 GIT_AUTHOR_DATE (3认同)
  • @Rahul不,不是,这是正确的方法/sf/answers/3973146621/ (2认同)

Vil*_*ira 18

下面是我使用的更改提交fooN=1在过去的日子:

git add foo
git commit -m "Update foo"
git commit --amend --date="$(date -v-1d)"
Run Code Online (Sandbox Code Playgroud)

如果你想提交一个更老的日期,比如3天前,只需更改date参数:date -v-3d.

例如,当你忘记昨天提交某些东西时,这非常有用.

更新:--date也接受像--date "3 days ago"或甚至--date "yesterday".所以我们可以将它减少到一行命令:

git add foo ; git commit --date "yesterday" -m "Update"
Run Code Online (Sandbox Code Playgroud)

  • 警告:`git --date`只会修改$ GIT_AUTHOR_DATE ...所以根据情况你会看到提交的当前日期($ GIT_COMMITTER_DATE) (4认同)

Mac*_*zyk 17

您正在寻找的简单答案:

GIT_AUTHOR_DATE="2020-10-24T18:00:00 +0200" GIT_COMMITTER_DATE=$GIT_AUTHOR_DATE git commit
Run Code Online (Sandbox Code Playgroud)

注意时区字符串并为您的时区设置一个合适的字符串。即+0200、-0400


Jst*_*oRR 16

在我的例子中,使用--date选项时,我的git进程崩溃了.可能是我做了一件可怕的事.结果出现了一些index.lock文件.所以我手动删除了.git文件夹中的.lock文件并执行了,因为所有修改过的文件都要在传递的日期提交,这次就可以了.谢谢所有答案在这里.

git commit --date="`date --date='2 day ago'`" -am "update"
Run Code Online (Sandbox Code Playgroud)

  • 请参阅[以上关于`git commit --date`的评论](http://stackoverflow.com/questions/3895453/how-do-i-make-a-git-commit-in-the-past#comment52277002_9778940).此外,应修改您的示例提交消息,以阻止像@JstRoRR这样的不良单行消息 (5认同)
  • 警告:`git --date`只会修改$ GIT_AUTHOR_DATE ...,因此,根据情况,您会看到提交的当前日期($ GIT_COMMITTER_DATE) (3认同)

okw*_*wap 11

  1. git --date仅更改GIT_AUTHOR_DATE但许多 git 应用程序,例如 GitHub 显示GIT_COMMITTER_DATE。确保GIT_COMMITTER_DATE也改变。
  2. git 不知道默认 UNIX 日期输出中的时区。确保将日期时间格式设置为兼容格式,例如 ISO8601。

OS X 中的完整示例(将GIT_COMMITTER_DATE和更改GIT_AUTHOR_DATE为 4 小时前):

x=$(date -v -4H +%Y-%m-%dT%H:%M:%S%z); export GIT_COMMITTER_DATE=$x; git commit --amend --date $x
Run Code Online (Sandbox Code Playgroud)


aks*_*hir 6

因此,如果您想在过去的日期在 Git 上提交某些内容,您只需使用这些命令即可帮助您完成此操作。

git commit --amend --no-edit --date="Sat Jun 5 20:00:00 2021 -0600"
Run Code Online (Sandbox Code Playgroud)
  1. 要在过去的日期进行提交,您只需通过运行以下命令将更改添加到本地存储库中:git add .
  2. 使用 提交更改git commit -m "Your commit message"
  3. git commit --amend --no-edit --date="Sat Jun 5 20:00:00 2021 -0600"提交后运行此命令以修改带有记录时间戳的最后一次提交。--no-edit 将使消息保持原样。
  4. 通过运行 git Push 将更改推送到 GitHub 或您使用的任何平台。

确保您必须根据您的喜好更改日期和时间。这将创建对过去特定日期的提交,并且您不会丢失 GitHub 记录。


rel*_*l1x 5

或者只是使用fake-git-history为特定的数据范围生成它。