How to checkout in Git by date?

Viewed 175604

I am working on a regression in the source code. I'd like to tell Git: "checkout the source based on a parameterized date/time". Is this possible?

I also have staged changes in my current view that I don't want to lose. Ideally, I would like to toggle back and forth between the current source, and some version I'm interested in based on a previous date.

14 Answers

Reminder, since Git 2.23 (Aug. 2019)

  • switch to a new branch from a past commit by date:

    git switch -c newBranch $(git rev-list -n1 --before=yyyy-mm-dd main)
    
  • restore a file at a past date in the current working tree

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

Do not use the old, obsolete and confusing git checkout command in 2021/2022: git switch and git restore describe exactly what they are doing (working with only branches for git switch, and only with files for git restore)

Do not use ``: prefer the more modern $(command substitution) syntax over obsolescent backtick syntax.

To create a new branch from the checkout, use -b option with new branch name.

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

You can avoid git switch, when you are in 'detached HEAD' state

Here's an alias version that I use to checkout by relative time:

[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)\""

This allows you to checkout your changes from 2 months ago into a new branch named test using the following command:

git codate '2 months ago' -b test

This won't work on a shallow clone so unshallow it first with:

git fetch --unshallow

If you get an unshallow error, you might find help from the excellent answer at git fatal: error in object: unshallow

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

Install on macos using brew install coreutils.

You only need a little change if you hit the limit of reflog (the date you cloned the repo or 90 days a go of history it seems from other notes)

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

And you can also use

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

it will checkout the previous commit related to the date or the date-time you enter, see that you can use modifiers for the date, I guess if you dont use UTC+-N it just uses UTC time.

See that I only changed master to HEAD, it seems to work even if you dont have reflog to the date you want to check!!!

If you want to check out a single file as of a specific date, you can pass the filepath to both commands.

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