【问题标题】:How to checkout in Git by date?如何按日期在 Git 中结帐?
【发布时间】:2011-10-22 20:37:56
【问题描述】:

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

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

【问题讨论】:

  • 以防万一您不知道,git bisect 非常适合查找回归。我想说,使用像 Andy 所说的 {1 year ago} 语法来找到一个已知良好的提交,然后将其用作您的初始 git bisect good 点。
  • 我觉得这是 tags 的一个很好的用例。

标签: git git-checkout


【解决方案1】:

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

换句话说,您使用rev-list 查找提交,然后使用结帐 真的明白了。

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

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

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

【讨论】:

  • 很好的链接!所以git checkout branch@{date}在reflog过期时停止工作,但你可以使用git checkout `git rev-list -n 1 --before="2009-07-27 13:37" master`
【解决方案2】:

保留您当前的更改

您可以使用git stash 将您的工作隐藏起来,而无需提交。你 不会使用git stash pop 来取回它。或者您可以(如 carleeto 所说)git commit 将其转移到一个单独的分支。

使用 rev-parse 按日期结帐

您可以使用 rev-parse 在特定日期之前签出提交,如下所示:

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

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

如 cmets 中所述,此方法使用 reflog 查找历史记录中的提交。默认情况下,这些条目 expire after 90 days。虽然使用 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。这就是你通常想要的。

【讨论】:

  • @Rocky 你能给我们更多的细节吗?你在命令行上输入了什么,为什么你说它不起作用?您收到错误消息了吗?
  • @Rocky:问题是参数需要用引号括起来,否则 bash 会在空格处分隔参数。试试git co 'master@{2 days ago}'
  • 注意:这取决于你回溯多远,这可能不起作用,因为它使用了 reflog(一段时间后过期)。您将看到“警告:'master' 的日志仅返回到...”。 Rocky 的解决方案将永远有效。 git checkout git rev-list -n 1 --before="2009-07-27 13:37" master
  • 我编辑了您的答案,因为反引号已被弃用且难以阅读。子shell $(...) 是首选。
  • @Andy 40 岁生日快乐,安迪! (假设这就是 1979-02-26 的意思:))
【解决方案3】:

Andy 的解决方案对我不起作用。在这里我找到了另一种方式:

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

Git: checkout by date

【讨论】:

  • 当我执行上述命令时,我得到error: unknown switch `n' 任何想法如何解决这个问题?
  • @Tim 分两部分运行,首先运行git rev-list,然后再运行git checkout,并使用从第一个命令获得的提交。
  • 你应该使用-n 1而不是--max-count=1
  • 您应该解释对选项的需求。为什么是-n 1?不通过有什么区别?
  • 这在 GIT for Windows 上根本不起作用! (GIT 版本 2.30.1)。看起来 rev-list 命令总是忽略任何此类输入命令行选项。 :-\
【解决方案4】:

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

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

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

【讨论】:

    【解决方案5】:

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

    git rev-list -n1 --before=2013-7-4 master | xargs git checkout
    

    【讨论】:

      【解决方案6】:

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

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

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

      【讨论】:

      • 虽然这并没有给我我寻找的答案,但它确实值得一提,因为它指出了迄今为止未提及的一个方面。这可能是导致您无法获得正确版本的问题的根源。
      【解决方案7】:

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

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

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

      git checkout SHA
      

      【讨论】:

        【解决方案8】:

        如果您感兴趣的日期是提交日期,@Andy 提出的git rev-parse 解决方案可以正常工作。但是,如果您想根据作者的日期结帐,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 }
        )
        

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

        【讨论】:

          【解决方案9】:
          git rev-list -n 1 --before="2009-07-27 13:37" origin/master
          

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

          git checkout XXXX
          

          【讨论】:

          • 这不是@bartoszkp 答案的副本吗?只是添加对原点的引用,应该是对另一个答案的评论......
          • 是的,实际上差不多,只是为不知道 SHA 是什么的人(比如我)清除要复制的内容,在我的情况下,文本不清楚,这是我在找到解决方案后的代码,没有复制,实际上你可以看到选项也略有不同
          【解决方案10】:

          如果你达到了 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到你要检查的日期,它似乎也可以工作!!!

          【讨论】:

            【解决方案11】:

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

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

            【讨论】:

              【解决方案12】:

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

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

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

              【讨论】:

                【解决方案13】:

                提醒,自 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 年使用 old, obsolete and confusing git checkout commandgit switchgit restore 准确描述他们在做什么(仅使用 git switch 的分支,并且仅使用 git restore 的文件)

                不要在过时的反引号语法上使用 ``:prefer the more modern $(command substitution) syntax

                【讨论】:

                  猜你喜欢
                  • 2016-06-18
                  • 2011-04-05
                  • 2022-11-02
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2012-06-27
                  • 2022-01-05
                  相关资源
                  最近更新 更多