implenton/

Automate explicit date assignments for Eleventy posts using Git log

Since version 1.0.1, 11ty can infer the date from the git log automatically.

The Eleventy website mentions relying on the date associated with a piece of content (e.g., date created) when CI (Continuous Integration) is involved as a common pitfall.

Be careful relying on the default date associated with a piece of content. By default Eleventy uses file creation dates, which works fine if you run Eleventy locally but may reset in some conditions if you run Eleventy on a Continuous Integration server. Work around this by using explicit date assignments, either in your front matter or your content’s file name.

Let's take the Netlify deployment process as an example.

When you create a project, you associate it with a Git repository. You do this because part of the deployment process, Netlify clones the repository. This is how it gets access to your files.

...
6:28:02 PM: Starting to prepare the repo for build
6:28:03 PM: Preparing Git Reference refs/heads/master
...

The "problem" is that the files' creation dates will be the time of the cloning. This is because files did not exist before on the CI "machine"; they are created as brand new files.

If you rely on the creation date, the articles you wrote two years ago will appear as published just right now.

The recommended workaround is to use explicit date assignments, aka put that date somewhere!

It makes sense. Still, it's a little annoying.

Say you are using WordPress (or any other CMS, really) for light-weight blogging, you usually don't set the date. The published date will be the time of clicking the "publish" button.

Of course, tradeoffs.


This got me thinking, is there something equivalent to the "publish" button when using a static site generator?

I think so. We can consider the time of committing the file the time of publishing.

We have access to this information as long as we keep the posts under version control. And yes, we can explicitly assign the dates automatically using this information!

Here's an idea of how to go about this.

Get the "published date" of a post (Markdown file).

git log --format=%as ./src/content/posts/commit-without-file-changes-in-git.md | tail -1

The %as for that format flag is the "author date, short format (YYYY-MM-DD)". There are multiple format types, for example, %at is the UNIX timestamp format, %aD uses the RFC2822 style.

These are documented; check the help manual using git log --help.

Instead of the typical log with the committer name, message, date, you get back this:

2021-12-27
2021-12-20
2021-12-13
2021-12-06
2021-12-04

tail -1 returns the contents of the last row, which is the date of the first-ever commit, aka the "published date".

Do this for multiple posts.

#!/bin/bash
FILES=$(find ./src/content/posts -maxdepth 1 -type f -name "*.md")

for FILE in $FILES
do
git log --format=%as "$FILE" | tail -1
done

The regular expression of the renaming part largely depends on what convention you use for naming your posts.

#!/bin/bash
FILES=$(find ./src/content/posts -maxdepth 1 -type f -name "*.md")

for FILE in $FILES
do
DATE_PUBLISHED=$(git log --format=%as "$FILE" | tail -1)
RENAMED_FILE=$(echo "$FILE" | sed -E "s/([A-Za-z0-9-]+)(\.md)/$DATE_PUBLISHED-\1\2/g" )
mv "$FILE" "$RENAMED_FILE"
done

(The script does not check if the returned files are empty or if the files already have the date prepended. If you sanity checks, make sure you added them.)

To deconstruct the regex pattern, check out the explanation on RegEx101. You will see information about the match and replacement. It essentially prepends the published date to the filename in the most straightforward way.

This bash script can be run during the deployment process on Netlify. If you previously ran npx @11ty/eleventy to build the website, you can just run the bash script before it:

./add-explicit-date-assignments-to-posts && npx @11ty/eleventy

Eleventy automatically removes the dates from the permalinks when it generates the HTML files. This means that it does not matter that after renaming, you ended up with files like this:

...
./src/content/posts/2021-12-04-commit-without-file-changes-in-git.md
...

2022-01-22