Using Git to see earlier code versions

I couldn’t think of a good title for this post, but this was the problem I found myself in, whilst doing some WordPress theme development.

I came to my computer this morning to continue work, and noticed that there was an “error_log” file in the “wp_admin” folder on the server.  So I downloaded it, had a look, and there was an error message from yesterday afternoon, something like this…

[21-May-2020 15:22:42 UTC] PHP Warning:  copy(/public_html/wp-content/uploads/2020/05/DSC0661.jpg): failed to open stream: No such file or directory in /public_html/wp-content/themes/custom-theme/functions.php on line 2346

The trouble is, I was working on this theme all evening, and so line number 2346 is no longer relevant to this message, so how do I work out what the line of code was at 3.22pm yesterday?

Well the answer to that, is Git.  It’s no coincidence that I use it for all my development projects, it’s a real lifesaver time and time again.

In this case, we need to take the current branch back to an earlier point in time, which we can do like this…

git checkout 'HEAD@{21-May-2020 15:22:42 UTC}'

As you can see, we used the timestamp exactly as it appeared in the PHP logfile, making this super easy. And we now have the code that we need and can check line 2346, which is now clearly the culprit of the error message…

copy($filename,$tmp_name);

And to restore ourselves back to the latest version of the code we can simply checkout our branch again (master, in my case), like this…

git checkout master

Please note, there are a couple of caveats to this:

  1. This uses reflog, so it only works for recent timestamps – by default they expire after 90 days and if it can’t find a log for before that timestamp it simply gives you the closest it can, which might not be the code you are looking for.
  2. This uses reflog, so it’s local only – if you are working on a shared repository it won’t give you the state of the remote, only what you had in your local at that time.

Anyway, with those caveats understood, this is still a neat trick that I found useful today for finding a line number in code at a specific timestamp.