377

我正在对源代码进行回归。我想告诉 Git:“根据参数化的日期/时间检查源代码”。这可能吗?

我也对我目前的观点进行了一些我不想失去的改变。理想情况下,我想在当前源和基于先前日期的某个我感兴趣的版本之间来回切换。

4

14 回答 14

429

保留您当前的更改

您可以使用git stash. 你不会用git stash pop它来取回它。或者您可以(如carleeto所说)git commit将它放到一个单独的分支中。

使用 rev-parse 按日期结帐

rev-parse您可以使用如下方式在特定日期签出提交:

git checkout 'master@{1979-02-26 18:30:00}'

有关可用选项的更多详细信息,请参阅git-rev-parse

如评论中所述,此方法使用 reflog 在您的历史记录中查找提交。默认情况下,这些条目会在 90 天后过期。尽管使用 reflog 的语法不那么冗长,但您只能返回 90 天。

使用 rev-list 按日期结帐

另一个不使用 reflog 的选项是用于rev-list在特定时间点获取提交:

git checkout `git rev-list -n 1 --first-parent --before="2009-07-27 13:37" master`

如果您只想要历史记录而不想要合并带来的版本,请注意--first-parent 。这就是你通常想要的。

于 2011-08-09T02:05:37.667 回答
148

安迪的解决方案对我不起作用。在这里,我找到了另一种方法:

git checkout `git rev-list -n 1 --before="2009-07-27 13:37" master`

Git:按日期结帐

于 2011-12-15T03:40:27.783 回答
19

看起来你需要类似这样的东西: Git checkout based on date

换句话说,您使用rev-list查找提交,然后使用结帐来实际获取它。

如果您不想丢失分阶段的更改,最简单的方法是创建一个新分支并将它们提交到该分支。您始终可以在分支之间来回切换。

编辑:链接已关闭,所以这里是命令:

git checkout `git rev-list -n 1 --before="2009-07-27 13:37" master`
于 2011-08-09T01:36:56.357 回答
15

对于那些喜欢管道而不是命令替换的人

git rev-list -n1 --before=2013-7-4 master | xargs git checkout
于 2013-12-09T05:42:57.957 回答
13

在我的情况下,该-n 1选项不起作用。在 Windows 上,我发现以下命令序列可以正常工作:

git rev-list -1 --before="2012-01-15 12:00" master

这将返回给定日期的适当提交的 SHA,然后:

git checkout SHA
于 2015-12-08T16:17:41.667 回答
5

git rev-parse如果您感兴趣的日期是提交的日期,@Andy 提出的解决方案可以正常工作。但是,如果您想根据作者的日期结帐,那rev-parse将不起作用,因为它不提供使用该日期来选择提交的选项。相反,您可以使用以下内容。

git checkout $(
  git log --reverse --author-date-order --pretty=format:'%ai %H' master |
  awk '{hash = $4} $1 >= "2016-04-12" {print hash; exit 0 }
)

(如果您还想$1 >= "2016-04-12" && $2 >= "11:37"awk谓词中指定时间使用。)

于 2016-08-13T09:43:50.890 回答
3

rev-list如果您想从您的主分支找到最新的合并提交到您的生产分支(作为一个纯粹的假设示例),则进一步使用该选项:

git checkout `git rev-list -n 1 --merges --first-parent --before="2012-01-01" production`

我需要找到截至给定日期在生产服务器上的代码。这为我找到了它。

于 2013-10-07T18:56:12.293 回答
3

如果您希望能够在进行构建时返回到存储库的精确版本,最好标记您进行构建的提交。

其他答案提供了将存储库返回到某个时间分支中最近提交的技术——但它们可能并不总是足够的。例如,如果您从一个分支构建,然后删除该分支,或者从一个稍后重新调整的分支构建,那么您构建的提交可能会在 git 中从任何当前分支变得“不可访问”。压缩存储库时,最终可能会删除 git 中无法访问的对象。

在提交上放置标签意味着它永远不会变得无法访问,无论您之后对分支做什么(除非删除标签)。

于 2015-12-04T22:57:35.227 回答
1
git rev-list -n 1 --before="2009-07-27 13:37" origin/master

获取打印的字符串(例如 XXXX)并执行以下操作:

git checkout XXXX
于 2017-05-05T14:38:24.980 回答
1

如果你达到了 reflog 的限制,你只需要做一点改变(你克隆 repo 的日期或 90 天的历史记录,从其他注释看来)

git checkout `git rev-list -1 --before="Jan 17 2020" HEAD`

你也可以使用

git checkout `git rev-list -1 --before="Jan 17 2020 8:06 UTC-8" HEAD`

它将检查与您输入的日期或日期时间相关的先前提交,看看您可以使用修饰符作为日期,我猜如果您不使用 UTC+-N 它只使用 UTC 时间。

看到我只把master改成HEAD,即使你没有reflog到你想检查的日期,它似乎也能工作!!!

于 2020-08-28T04:36:32.230 回答
0

如果要在特定日期检出单个文件,可以将文件路径传递给这两个命令。

git checkout `git rev-list -n 1 --before="2009-07-27 13:37" master FILEPATH` FILEPATH
于 2021-10-23T00:52:20.967 回答
0

要从结帐中创建新分支,请使用带有新分支名称的 -b 选项。

git checkout -b 19July2021 `git rev-list -n1 --before=2021-7-19 master`

git switch当您处于“分离 HEAD”状态时,您可以避免

于 2021-12-14T11:47:29.363 回答
0

提醒,从 Git 2.23(2019 年 8 月)开始

  • 按日期从过去的提交切换到新分支:

    git switch -c newBranch $(git rev-list -n1 --before=yyyy-mm-dd main)
    
  • 在当前工作树中恢复过去日期的文件

    git restore -SW -s $(git rev-list -n1 --before=yyyy-mm-dd main) -- path/to/file
    

不要在 2021/2022 年 使用旧的、过时且令人困惑的git checkout命令git switch:并git restore准确描述他们在做什么(仅使用 的分支git switch,仅使用 的文件git restore

不要使用 ``:比过时的反引号语法更喜欢更现代的$(command substitution)语法。

于 2021-12-14T13:29:40.483 回答
0

这是我用来按相对时间结帐的别名版本:

[alias]
    parsedate = "!set -x ;arg1=\"$1\" && shift && which gdate &> /dev/null && gdate -d \"$arg1\" || date -d \"$arg1\""
    codate = "!d=\"$(git parsedate \"$1\")\" && shift && git checkout \"$(git rev-list -n1 --first-parent --before=\"$d\" HEAD)\""

test这使您可以使用以下命令将2 个月前的更改签出到名为的新分支中:

git codate '2 months ago' -b test

这不适用于浅克隆,因此首先使用以下方法使其不浅:

git fetch --unshallow

如果你得到一个不浅的错误,你可能会从git fatal: error in object: unshallow的优秀答案中找到帮助

Requires GNU coreutils and works on Linux and macOS using brew.

Install on macos using brew install coreutils.

于 2022-02-16T21:36:19.693 回答